Programmatically apply Knockout bindings to specif

2019-05-28 20:54发布

I have a block of html markup that I'd like to databind to a div using Knockout JS. This is simple enough with the knockout html binding.

What I'd like to do is conditionally bind child elements within that html markup, based on their class. These elements can appear anywhere within the html markup, as they are inline elements (like span, a tags, etc).

The purpose of this is to databind click events to specific words or phrases within this text block, so that I can call a function (in this case, a modal with a definition of the target word or phrase).

Does anyone know how to do this? From what I can see, I have two main avenues to explore:

  1. Use jQuery to grab the elements by class, and somehow databind to then after the fact. I don't know if this will work for various reasons - not having the DOM ready, not being able to databind in that method, etc.

  2. Use knockout's template binding, and add an afterRender template callback that parses the text block for the elements and databinds them accordingly.

  3. A combination of the two above. (Yeah, I know, that's three avenues.)

Has anyone done anything like this before? I'd like to get your advice and feedback, if possible. Thank you!

1条回答
Anthone
2楼-- · 2019-05-28 21:31

I don't recommend this approach unless you are sure that the html you are binding to is safe. The html binding looks like this.

ko.bindingHandlers['html'] = {
    'init': function() {
        // Prevent binding on the dynamically-injected HTML 
        // (as developers are unlikely to expect that, and it 
        // has security implications)
        return { 'controlsDescendantBindings': true };
    },
    'update': function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        ko.utils.setHtml(element, value);
    }
};

Looking at this you could write a html2 binding

ko.bindingHandlers['html2'] = {
    'init': function() {
        return { 'controlsDescendantBindings': false };
    },
    'update': function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        ko.utils.setHtml(element, value);
    }
};

http://jsfiddle.net/madcapnmckay/LDtuF/1/

Be careful with this, you want to make sure the html cannot be used for insecure purposes.

Hope this helps.

查看更多
登录 后发表回答