Knockout components (not) binding on new content

若如初见. 提交于 2021-02-06 08:42:18

问题


Redacted question and example

I'm trying to get Knockout components to bind after the initial ko.applyBindings(); so I can add custom elements dynamically.

In my original post I referred to loading content by ajax, but my problem occurs when custom elements are added to the DOM using something like jQuery append.

Here's an example:

$(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>

Original post

I've successfully created my new component, <mynew-widget></mynew-widget>

I've seen the joy of peppering my page with them and everything works beautifully... until I load new content (an AJAX-loaded modal popup, for example) which contains <mynew-widget></mynew-widget>. Nothing happens.

Is this a limitation of Knockout or have I wired things up incorrectly?

Please tell me it's the latter - as I love not having to worry about when/where to call ApplyBindings and on which parts of the DOM.

Thinking it through, I understand knockout needs to notice that the custom elements have been added to the DOM - but I was hoping it might just work in a jQuery '$().on(...)' kind of way.


回答1:


The component binding doesn't happen magically: it happens when you call ko.applyBindings();. At this moment, the bound HTML is searched for components, and they are bound.

Later on, when you dynamically add a new component to the page, it's not bound, unless you explicitly bind it. So, in your code, the component is fully ignored.

As stated, what you need to do is to explicitly bind it. But you must take into account that you cannot bind nodes that have already been bound. However it's extremely easy to create a node with jquery, append it to the DOM, and bind it. There is a syntax to specify the viewmodel and the node to which you want to bind it: ko.applyBindings(viewModel, node);

Here you have a full working sample in jsfiddle. This is the code in that fiddle:

HTML:

Here's a widget, declared 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]);
});

NOTE: when calling apply bindings I pass an empty objet: don't pass a null, or you'll get an error. If your template includes a viewmodel, it will be used independently of the passed view model.

NOTE: $newWidget is a jquery object. $newWidget[0] is the first (and only, in this case) DOM element of the jQuery object, as required by applyBindings



来源:https://stackoverflow.com/questions/27137834/knockout-components-not-binding-on-new-content

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!