Don Box
Don Box

Reputation: 3336

custom logic on elements addef by "if" binding with virtual elements

I'm using the containerless control flow syntax for 'if' binding:

<!-- ko if: property -->
<div>
    <button type="button">My Button</button>
</div>

I am also using a UI library which for initialization requires calling in JS something like this:

$("body").initLib();

which will make the button work and feel in a certain way.

But since the button is a virtual element added based on the 'if' binding, the library won't add the functionality for the button.

What's the best way to handle this scenario? Can I extend the 'if' binding for virtual elements?

Upvotes: 1

Views: 137

Answers (2)

JotaBe
JotaBe

Reputation: 39055

If you can modify the initLib code, the best way to do it is to use delegated events, which doesn't depend on the element existing on the page when registering the event handlers. The logic behind this is that the event bubbles up the DOM tree, so you register the handling in a container which is fixed in the page, for example body, and then specify the event to handle and a selector. So, if the user clicks the button, the event bubbles up to the body element, and, if it fulfils the filter, the event is handled. It doesn't matter if the element was there when you registered the handling. This is done by using $.on(), for example:

$('body').on('click', 'input[type=button]' , function() { /* handler */});

To implement the filter, which in this case selects all the buttons, you can use the id, or add data- attributes to the element (button), so that you can filter them.

jQuery docs on on(), and delegated events

If you cannot modify the library, instead of using the if binding, you can use the visible binding. In this way the handlers can be registered, and they won't be lost. NOTE: I think you cannot use visible on a virtual element, but you can use an element with appropriate styling to make it look as if it isn't there.

NOTE: in general you should try to avoid mixing ko with jQuery, because they use different approaches and using them together can lead to conflicts.

Upvotes: 0

Dandy
Dandy

Reputation: 2177

One way is to create a custom binding like

  ko.bindingHandlers.myLibInit = {
      init: function(element, valueAccessor) {
          $("body").initLib();
      }
  };

and have your virtual element like

  <!-- ko if: property -->
  <div>
      <button type="button" data-bind="myLibInit:{}">My Button</button>
  </div>
  <!-- /ko -->

Upvotes: 2

Related Questions