Подтвердить что ты не робот

Компоненты нокаута (не) привязываются к новому контенту

Исправленный вопрос и пример

Я пытаюсь связать компоненты 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="[email protected]*" data-semver="3.2.0" rel="stylesheet" href="#" onclick="location.href='http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'; return false;" />
<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 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 template is not bound, so nothing appears. How do I get it to bind/appear?</p>


</body>
4b9b3361

Ответ 1

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

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

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

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

HTML:

Здесь виджет, объявленный inline:     

  <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]);
});

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

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