Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I access ::content elements in Polymer

Tags:

polymer

Is it possible to access an element in the "content" area in Polymer?

Let me show an example:

<my-element>
  <my-sub-element1></my-sub-element1>
  <my-sub-element2></my-sub-element2>
</my-element>

I would like to let my-element to fetch some data to from a rest service using iron-ajax, and then display some content in my-sub-element1 and my-sub-element2. Is this possible without transferring the data through properties? my-sub-element1 and 2 should only be used within the context of my-element.

I tried to do a document.querySelector(":host ::content"), but it returned null so I guess that is not the way to do it :)

like image 838
Andreas Selenwall Avatar asked Jan 28 '26 20:01

Andreas Selenwall


1 Answers

I'd like to supplement the other potentially correct answers with more details and a demo...

Polymer.dom(this).querySelectorAll('my-sub-element')

While this method would work in your example use case, it would break if your container element were wrapped in another container, as demonstrated below. Here, my-element would not find any elements with querySelectorAll('my-sub-element1') (although my-element-wrapper would).

Further, this limits future extensibility of your element (e.g., by a third party who cannot modify the original element), which might not be an immediate concern for you.

<head>
  <base href="https://polygit.org/polymer+1.4.0/components/">
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
  <link rel="import" href="polymer/polymer.html">
</head>

<body>
  <my-element-wrapper>
    <my-sub-element1></my-sub-element1>
    <my-sub-element2></my-sub-element2>
  </my-element-wrapper>

  <dom-module id="my-element">
    <template>
      <content></content>
    </template>
    <script>
      Polymer({
        is: 'my-element',
        ready: function() {
          var el = Polymer.dom(this).querySelectorAll('my-sub-element1');
          console.log('my-element > my-sub-element1:',
                      'length=' + el.length,
                      'element=' + (el.length > 0 ? el[0].tagName : "''"));
        }
      });
    </script>
  </dom-module>

  <dom-module id="my-sub-element1">
    <script>
      Polymer({ is: 'my-sub-element1' });
    </script>
  </dom-module>

  <dom-module id="my-sub-element2">
    <script>
      Polymer({ is: 'my-sub-element2' });
    </script>
  </dom-module>

  <dom-module id="my-element-wrapper">
    <template>
      <my-element>
        <content></content>
      </my-element>
    </template>
    <script>
      Polymer({ is: 'my-element-wrapper' });
    </script>
  </dom-module>

</body>

jsbin

Polymer.getContentChildren()

This method gets the distributed child elements from your container element's <content>, which indeed gets you closer to a flexible solution because a wrapper container (like in the previous example) would not change its results.

However, this gets all distributed children, so it would be inconvenient (and perhaps even inefficient) if you were only interested in a subset.

<head>
  <base href="https://polygit.org/polymer+1.4.0/components/">
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
  <link rel="import" href="polymer/polymer.html">
</head>

<body>
  <my-element-wrapper>
    <my-sub-element1></my-sub-element1>
    <my-sub-element2></my-sub-element2>
  </my-element-wrapper>

  <dom-module id="my-element">
    <template>
      <content></content>
    </template>
    <script>
      Polymer({
        is: 'my-element',
        ready: function() {
          var el = this.getContentChildren().filter(function(item) {
            return item.tagName.toLowerCase() === 'my-sub-element1';
          });
          console.log('my-element > my-sub-element1:',
                      'length=' + el.length,
                      'element=' + (el.length > 0 ? el[0].tagName : "''"));
        }
      });
    </script>
  </dom-module>

  <dom-module id="my-sub-element1">
    <script>
      Polymer({ is: 'my-sub-element1' });
    </script>
  </dom-module>

  <dom-module id="my-sub-element2">
    <script>
      Polymer({ is: 'my-sub-element2' });
    </script>
  </dom-module>

  <dom-module id="my-element-wrapper">
    <template>
      <my-element>
        <content></content>
      </my-element>
    </template>
    <script>
      Polymer({ is: 'my-element-wrapper' });
    </script>
  </dom-module>

</body>

jsbin

Polymer.queryAllEffectiveChildren()

This method combines the two solutions above by fetching specific distributed children by a CSS selector. (It also seems to perform better than the other two. I'm not a JS perf expert, so those results could be inaccurate due to bad implementation.)

<head>
  <base href="https://polygit.org/polymer+1.4.0/components/">
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
  <link rel="import" href="polymer/polymer.html">
</head>

<body>
  <my-element-wrapper>
    <my-sub-element1></my-sub-element1>
    <my-sub-element2></my-sub-element2>
  </my-element-wrapper>

  <dom-module id="my-element">
    <template>
      <content></content>
    </template>
    <script>
      Polymer({
        is: 'my-element',
        ready: function() {
          var el = this.queryAllEffectiveChildren('my-sub-element1');
          console.log('my-element > my-sub-element1:',
                      'length=' + el.length,
                      'element=' + (el.length > 0 ? el[0].tagName : "''"));
        }
      });
    </script>
  </dom-module>

  <dom-module id="my-sub-element1">
    <script>
      Polymer({ is: 'my-sub-element1' });
    </script>
  </dom-module>

  <dom-module id="my-sub-element2">
    <script>
      Polymer({ is: 'my-sub-element2' });
    </script>
  </dom-module>

  <dom-module id="my-element-wrapper">
    <template>
      <my-element>
        <content></content>
      </my-element>
    </template>
    <script>
      Polymer({ is: 'my-element-wrapper' });
    </script>
  </dom-module>

</body>

jsbin

like image 75
tony19 Avatar answered Jan 30 '26 11:01

tony19



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!