Can dynamically created Local/Light DOM in Polymer

2020-03-24 07:47发布

问题:

Is it possible to modify local/light DOM from JS within a custom element in a way that would process bindings for thus dynamically added elements as if they were specified in template?

Please consider the following snippet (a part of a custom element):

...
            attached: function () {
                var node = document.createElement('div');                        
                Polymer.dom(node).innerHTML = '[[_computedValue()]]';
                Polymer.dom(this.$.container).appendChild(node);
                Polymer.dom.flush();
            },

            _computedValue: function() {
                return "some value";
            },
...

What I would like to happen is for the added div to have its inner HTML equal to the value returned from method _computedValue. The value cannot be assigned at the time of div creation as in the real situation it would depend on the realtime context.

回答1:

It appears that for now Polymer 1.0 does not support dynamic (imperative) bindings. Here and here are the relevant discussions.

The information from the above links suggests a reliable, albeit limited, approach to creation of dynamic content with bindings by means of using dom-bind template elements. The limitation is due to bindings working strictly with locally defined methods and properties for the dom-bind instance being created.

Here is an example, where domBind is created imperatively with properties tapCount, tapMessage and method _tapMe. The latter is used as on-tap event handler for the added to the domBind element div.

attached: function () {
   var domBind = document.createElement('template', 'dom-bind');
   domBind.tapCount = 0;
   domBind.tapMessage = 'Tap me now!';
   domBind._tapMe = function(e) {
                this.tapCount = this.tapCount + 1;
                this.tapMessage = 'Tapped ' + this.tapCount + ' time(s).';
   };
   var div = domBind.content.ownerDocument.createElement('div');
   div.innerHTML = '<b on-tap="_tapMe">[[tapMessage]]</b>';
   domBind.content.appendChild(div);
   Polymer.dom(this.$.container).appendChild(domBind);
   Polymer.dom.flush();
}

A similar to my question is posted here, which helped me to get a better appreciation for the scope of the problem (especially with the reference to Polymer 0.5 injectBoundHTML).


Of course, external methods and properties can still be accessed:

...
var self = this;
domBind.externalMethod = function() {
    return self._computeValue();
};
...

Then by binding locally defined externalMethod one can "bind" things from the "external" scope. In this case, _computeValue refers to a method defined on a custom element with imperative light DOM construction happening in its method attached.