Skip to content Skip to sidebar Skip to footer

Knockoutjs + Polymer: Bindings Break (outside Of Chrome)

EDIT: This only appears outside of Chrome I'm using KO to fill in elements using foreach bindings. On the other side of the coin, I've got Polymer loaded up to make use of Google's

Solution 1:

If anyone has this issue, it is because you are using the ko.applyBindings(viewModel) method, and in here knockout uses window.document.body to get the node, which in turn misses the shadowDOM polyfill which webcomponents.js uses.

To get around this, you have two options, use the second overload of the apply bindings method - you'll probably get a successfully wrapped node this way.

Alternatively, you can load this shim immediately after the knockout declaration (some boilerplate borrowed from knockout.validation:

(function (factory) {
    // Module systems magic dance.if (typeofrequire === "function" && typeofmodule === "object") {
        // CommonJS or Node: hard-coded dependency on "knockout"factory(require("knockout"));
    } elseif (typeof define === "function" && define["amd"]) {
        // AMD anonymous module with hard-coded dependency on "knockout"define(["knockout"], factory);
    } else {
        // <script> tag: use the global `ko` object, attaching a `mapping` propertyfactory(ko);
    }
}(function (ko) {

    if (typeof (ko) === undefined) { throw'Knockout is required, please ensure it is loaded before loading this shim'; }

    if (WebComponents && WebComponents.flags.shadow && ShadowDOMPolyfill) {

        var _originalApplyBindings = ko.applyBindings;

        ko.applyBindings = function (viewModel, rootNode) {
            if (rootNode) {
                rootNode = ShadowDOMPolyfill.wrapIfNeeded(rootNode);
            } else {
                rootNode = ShadowDOMPolyfill.wrapIfNeeded(window.document.body);
            }
            _originalApplyBindings(viewModel, rootNode);
        }
    }
}));

Hopefully this helps anyone with the same issue.

Solution 2:

My fix for this has been to use jQuery to insert the DOM element with the foreach binding, and then apply my KO bindings inside a $(document).ready(function() {}); tag. This appears to work on all browsers.

While this isn't a great fix - it is the only one that has worked properly. I've reached out to Steve Sanderson of KnockoutJS and believe he's looking into it. The reason that I went with this fix over just using Knockout Custom components, is that the Polymer components offer Material Design as per Google's new design specs, and the web front-end that I'm building is intrinsically tied to my company's mobile application, so I wanted to maintain a cohesive design.

Post a Comment for "Knockoutjs + Polymer: Bindings Break (outside Of Chrome)"