Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use knockoutjs virtual element to create html part on the fly

I am trying to use "virtual element" with html binding to create html part on the fly but failed with message: "The binding 'html' cannot be used with virtual elements". Here is the jsfiddle: http://jsfiddle.net/d3Dpp/.

Anyone knows if there is any workaround?

like image 335
Gelin Luo Avatar asked Mar 13 '12 06:03

Gelin Luo


2 Answers

Based on Artem's code and KnockoutJS 2.2.1, here's an improved version:

http://jsfiddle.net/YZzDe/2/

Improvements:

  1. Less code, less duplication (hooks in to exposed interfaces)
  2. Overrides 'html' binding, so basically the old 'html' can now be used in virtuals
  3. No more global functions.

Here's the code

{
    var overridden = ko.bindingHandlers['html'].update;

    ko.bindingHandlers['html'].update = function (element, valueAccessor) {
        if (element.nodeType === 8) {
            var html = ko.utils.unwrapObservable(valueAccessor());

            ko.virtualElements.emptyNode(element);
            if ((html !== null) && (html !== undefined)) {
                if (typeof html !== 'string') {
                    html = html.toString();
                }

                var parsedNodes = ko.utils.parseHtmlFragment(html);
                if (parsedNodes) {
                   var endCommentNode = element.nextSibling;
                   for (var i = 0, j = parsedNodes.length; i < j; i++)
                      endCommentNode.parentNode.insertBefore(parsedNodes[i], endCommentNode);
                }
            }
        } else { // plain node
            overridden(element, valueAccessor);
        }
    };
}
ko.virtualElements.allowedBindings['html'] = true;
like image 100
Martijn Avatar answered Nov 17 '22 07:11

Martijn


Well, after some playing with knockout I see that it is possible.

Working example is here

http://jsfiddle.net/d3Dpp/42/

unfortunatelly this requires duplication of some internal knockout functionality

UPDATE

KnockoutJS 2.2.1 added virtual elements binding to export, so it is available even in minified version:

ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);

It means that better solution for html binding is possible - see Martijn's answer.

like image 7
Artem Avatar answered Nov 17 '22 07:11

Artem