13

Suppose I have two distinct polymer-elements

One should be embedded inside the other using the content placeholder. Is it possible to do data-binding between these two nested polymer-elements ?

I tried, but I can't get it to work: http://jsbin.com/IVodePuS/11/

According to http://www.polymer-project.org/articles/communication.html#binding data-binding between polymer-elements should work (in those examples they were done inside the template tag without using a content placeholder).

Update:

Scott Miles clarified that data-binding only works on the template level.
However in my case I don't know the exact template beforehand but I want to allow the user of my parent-element to specify which child-element it should contain (provided that there are different child-elements.
I think this question is related to this one: Using template defined in light dom inside a Polymer element

I updated the example below to highlight his:

<polymer-element name="parent-element" >
  <template >
    <div>Parent data: {{data1}} </div>
    <content />
  </template>
  <script>
    Polymer('parent-element', {
      data1 : '',
      ready: function() {
        this.data='parent content';
      }
    });

  </script>
</polymer-element>

<polymer-element name="child-element" attributes="data2">
   <template>
    <div>Parent data: {{data2}} </div>
  </template>
  <script>
    Polymer('child-element', {
      data2 : '',
      ready: function() {
      }
    });
  </script>
</polymer-element>

<polymer-element name="child2-element" attributes="data2">
   <template>
    <div>Parent data: {{data2}} </div>
  </template>
  <script>
    Polymer('child2-element', {
      data2 : '',
      ready: function() {
      }
    });
  </script>
</polymer-element>

The user can choose which child-element to embed:

<parent-element data1 = "test">
  <child-element data2="{{data1}}"/>
</parent-element>

<parent-element data1 ="test" >
  <child2-element data2="{{data1}}"/>
</parent-element>

Workaround:

The only workaround I found was to add change watcher and use getDistributedNodes() to get the child element and manually set data2 to data:

<polymer-element name="parent-element" >
  <template >
    <div>Parent data: {{data}} </div>
    <content id="content"/>
  </template>
  <script>
    Polymer('parent-element', {
      data : '',
      ready: function() {
        this.data='parent content';
      },
      dataChanged : function() {
          contents = this.$.content.getDistributedNodes();
          if (contents.length > 0) {
              contents[0].data2 = this.data;
          }
      },
    });

  </script>
</polymer-element>
Community
  • 1
  • 1
Ümit
  • 17,379
  • 7
  • 55
  • 74

3 Answers3

6

Polymer data-binding works by attaching a model to a whole subtree.

You wrote:

<parent-element>
  <child-element data2="{{data}}"/>
</parent-element>

this implies a rule that the parentNode provides the binding model. But now imagine you wanted to write:

<parent-element>
  <div>
    <child-element data2="{{data}}"></child-element>
  </div>
</parent-element>

Now you have a problem.

Instead, in Polymer examples, you will notice that the {{}} are (almost always) inside of a template. For example, if I define:

<polymer-element name="host-element" attributes="data" noscript>
<template>
  <parent-element data1="{{data}}">
    <child-element data2="{{data}}"></child-element>
  </parent-element>
</template>
</polymer-element>

Now, I have a model context (host-element) that I can use to bind things together in the entire subtree described by the template.

Note that I don't need attributes="data" for this to work. I added that so host-element exposes data and I can do this:

<host-element data="test"></host-element>  

http://jsbin.com/IVodePuS/15/edit

Scott Miles
  • 11,025
  • 27
  • 32
  • Minor note that this jsbin only seems to work on Canary. With the polyfills, it appears that the use of the host-element needs to follow its declaration. – DocDude May 07 '14 at 18:09
  • Element usage never needs to follow declaration. Where are you testing? I tested it in Chrome 34, FF 29, IE 11 and it worked fine as is. – Scott Miles May 07 '14 at 19:15
  • My mistake. Something was funky with my machine. Post crash & reboot, the jsbin works perfectly on Chrome 35, where I ran it before. – DocDude May 07 '14 at 21:26
  • Thanks a lot @ScottMiles for the feedback. However my specific use case is that I don't know the exact template during design time but only during runtine. Imagine I have two different `child-elements` and I want the user of my `parent-element` to choose `child-element` should be used. I updated the question. – Ümit May 08 '14 at 07:58
  • sheesh polymer is just so complex, yuk – SuperUberDuper Nov 24 '15 at 21:23
0

Works like a charm. Parent element is publishing property data, that can by 2 way data bound. This way the child element gets the same data.

<polymer-element name="custom-element">
<template>
    <parent data="{{data}}">
        <child data="{{data}}"></child>
    </parent>
</template>
<script>
    Polymer({
        ready: function() {

        },
        data: {}
    });
</script>

zdarsky.peter
  • 6,188
  • 9
  • 39
  • 60
0

I think in Polymer >= 1.0 this should be done using "Auto-binding template".

T. Roggendorf
  • 91
  • 1
  • 4
  • 1
    Welcome to Stack Overflow! Your answer could benefit from a specific example and more information about the link. Helpful hints do make great comments though. See [answer] for some helpful suggestions. – Hank D Apr 23 '16 at 23:54