Компоненты нокаута (не) обязательны для нового контента

Отредактированный вопрос и пример

Я пытаюсь заставить компоненты Knockout связываться после начальной ko.applyBindings(); поэтому я могу добавлять пользовательские элементы динамически.

В моем первоначальном посте я упоминал о загрузке контента с помощью ajax, но моя проблема возникает, когда пользовательские элементы добавляются в DOM с использованием чего-то вроде jQuery. append,

Вот пример:

$(function() {

  // Register a simple widget:
  ko.components.register('like-widget', {
    template: '<div class="alert alert-info">This is the widget</div>'
  });

  // Apply bindings
  ko.applyBindings();


  // Wire up 'add' button:
  $('#btnAdd').on('click', function() {

    $('#addZone').append("<like-widget></like-widget>");


  });

});
<link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<body>

  Here's a widget, declared inline:
  <like-widget></like-widget>

  <button id='btnAdd'>Add a new widget to the grey box:</button>
  <br/><br/>

  <div id='addZone' class="well">
    Widgets will be appended here
  </div>

  <p>When you run this code, the widget custom element is indeed added to the box (see source) but the widget's template is not bound, so nothing appears. How do I get it to bind/appear?</p>


</body>

Оригинальный пост

Я успешно создал свой новый компонент, <mynew-widget></mynew-widget>

Я видел радость от того, что перелистывал мою страницу, и все прекрасно работает... пока я не загружаю новый контент (например, модальное всплывающее окно, загруженное AJAX), который содержит <mynew-widget></mynew-widget>, Ничего не произошло.

Это ограничение нокаута, или я неправильно соорудил?

Пожалуйста, скажите мне, что это последнее - так как мне нравится не беспокоиться о том, когда и где вызывать ApplyBindings и в каких частях DOM.

Размышляя об этом, я понимаю, что нокаут должен заметить, что пользовательские элементы были добавлены в DOM - но я надеялся, что он может просто работать в jQuery ' $().on(...) такой способ.

1 ответ

Решение

Привязка компонента не происходит волшебным образом: это происходит при вызове ko.applyBindings();, В этот момент в связанном HTML ищутся компоненты, и они связаны.

Позже, когда вы динамически добавляете новый компонент на страницу, он не привязывается, если вы явно не связываете его. Итак, в вашем коде компонент полностью игнорируется.

Как уже говорилось, вам нужно явно связать это. Но вы должны принять во внимание, что вы не можете связать узлы, которые уже были связаны. Однако создать узел с помощью jquery чрезвычайно просто, добавить его в DOM и связать его. Существует синтаксис для указания модели представления и узла, к которому вы хотите привязать ее: ko.applyBindings(viewModel, node);

Здесь у вас есть полный рабочий образец в jsfiddle. Это код в этой скрипке:

HTML:

Вот виджет, объявленный встроенным:

  <button id='btnAdd'>Add a new widget to the grey box:</button>
  <br/><br/>

  <div id='addZone' class="well">
    Widgets will be appended here
  </div>

JavaScript:

ko.components.register('like-widget', {
    template: '<div class="alert alert-info">This is the widget</div>'
  });

ko.applyBindings()

$('#btnAdd').on('click', function() {
   // Create your widget node
   var $newWidget = $('<like-widget>');
   // Append it to your "append area"
   $('#addZone').append($newWidget);
   // Apply bindings to the newly added node
   ko.applyBindings({}, $newWidget[0]);
});

ПРИМЕЧАНИЕ: при вызове применения привязок я передаю пустой объект: не пропускайте ноль, иначе вы получите ошибку. Если ваш шаблон включает модель представления, он будет использоваться независимо от переданной модели представления.

ПРИМЕЧАНИЕ. $ NewWidget является объектом jquery. $ newWidget [0] - это первый (и единственный, в данном случае) элемент DOM объекта jQuery, как того требует applyBindings.

Другие вопросы по тегам