Search code examples
polymerpolymer-1.0web-componentcustom-element

On attached, `this.$` an empty object


I'm trying to observe added and removed dom nodes to my custom Polymer element without success. I've noticed that the this.$ is an empty object.

  Polymer({
    is: 'dramatic-view',
    attached: function () {
      this._observer = Polymer.dom(this.$.contentNode).observeNodes(function (info) {
        console.log('kromid info', info);
      });
    }
  });

The callback is being called only once (even tho I change content afterwards) with the following strange parameters:

console output

I was following the docs here.


Solution

  • this.$ is a hash of elements in your template that have an id attribute (see Automatic node finding).

    So, for this.$.contentNode to exist, you need an element with id="contentNode" in your <dom-module>'s <template>, and it must not be inside a dom-if or dom-repeat template:

    <dom-module id="x-foo">
      <template>
        <content id="contentNode"></content>
      </template>
    </dom-module>
    

    Nodes created dynamically (i.e., those inside dom-if or dom-repeat) must be queried with this.$$() (e.g., this.$$('#contentNode')). If you're trying to set them up in the attached callback, you'll need to wait until after the nodes are stamped, which could be observed with Polymer.RenderStatus.afterNextRender().

    <dom-module id="x-foo">
      <template>
        <template is="dom-if" if="[[useDynamicContent]]">
          <content id="contentNode"></content> <!-- unavailable to this.$ -->
        </template>
      </template>
      <script>
        Polymer({
          is: 'x-foo',
          attached: function() {
            Polymer.RenderStatus.afterNextRender(this, function() {
              var contentNode = this.$$('#contentNode');
              if (contentNode) {
                contentNode.observeNodes(...);
              }
            });
          }
        });
      </script>
    </dom-module>
    

    To trigger the node observer, use Polymer's DOM API like this:

    Polymer.dom(this).appendChild(node);
    Polymer.dom(this).removeChild(node);
    

    codepen

    UPDATE It seems you're integrating Polymer with Elm, and expecting to see the observer callback for node-changes made my Elm. You'll need to hook Elm's calls to appendChild/removeChild somehow so that it uses Polymer's DOM API.