Linking data between two polymer elements using polymer 1.0

Question

In the example below, how do I bind the variable obj.name the <input> field in <test-element2> to <test-element> ?


Background:

Below is my code. I have two polymer elements. test-element has data bound to obj.name . test-element2 has an input field that is observed by the objChanged function. No matter what value changes in the input field, it changes and prints in test-element2 , but the change is not reflected in test-element . Can any body help get the value reflected on test-element1 ? I have a solution using this.fire("object-change") when the text changes, but I'm looking for a solution without using event listeners.

One more thing: I need to create an element from a script, and it cannot be hardcoded in the HTML DOM.


The code:
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Demo</title> <script src="../../bower_components/webcomponentsjs/webcomponents-lite.js"></script> <link rel="import" href="../../bower_components/polymer/polymer.html"/> </head> <body> <dom-module id="test-element"> <template> <div>Hello <span>{{obj.name}}</span></div> </template> <script> TestElement = Polymer({ is: "test-element", properties: { "obj": { type: Object, notify: true } }, observers: [ "objChanged(obj.name)" ], "objChanged": function() { var that = this; console.log("First element in 1",that.obj); } }); </script> </dom-module> <dom-module id="test-element2"> <template> <input value="{{obj.name::input}}"/> </template> <script> Polymer({ is: "test-element2", properties: { "obj": { type: Object, notify: true, value: { "name": "Charlie" } } }, observers: [ "objChanged(obj.name)" ], ready: function() { var element = new TestElement(); element.set("obj", this.obj); this.appendChild(element); }, "objChanged": function() { console.log("changed in test-element2:", this.obj); } }); </script> </dom-module> <test-element2></test-element2> </body> </html> 
+5
source share
5 answers

If you included <test-element> in the <template> of test-element2 , you can avoid using event listeners or observers. This way test-element2 handles the data binding between input and <test-element> for you.

The following is a working example that supports the obj property since you configured it in your elements.

 <script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents.min.js"></script> <link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"> <dom-module id="test-element"> <template> <div>Hello <span>[[obj.name]]</span> </div> </template> <script> TestElement = Polymer({ is: "test-element", properties: { "obj": { type: Object, notify: true } } }); </script> </dom-module> <dom-module id="test-element2"> <template> <input value="{{obj.name::input}}" /> <test-element obj="[[obj]]"></test-element> </template> <script> Polymer({ is: "test-element2", properties: { "obj": { type: Object, notify: true, value: { "name": "Charlie" } } } }); </script> </dom-module> <test-element2></test-element2> 

Mandatory data binding is not currently supported in Polymer 1.0 outside of <template is="dom-bind"> .

I would recommend setting up observers as an example below, or test-element2 up your requirements to include <test-element> in test-element2 .

 button { display: block; } 
 <script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents.min.js"></script> <link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"> <dom-module id="test-element"> <template> <div>Hello <span>[[obj.name]]</span> </div> </template> <script> TestElement = Polymer({ is: "test-element", properties: { obj: { type: Object, notify: true } } }); </script> </dom-module> <dom-module id="test-element2"> <template> <input value="{{obj.name::input}}" /> </template> <script> Polymer({ is: "test-element2", properties: { obj: { type: Object, notify: true, value: { "name": "Charlie" } } }, observers: ["objNameChanged(obj.name)"], objNameChanged: function(newValue) { Polymer.dom(document).querySelectorAll("test-element").forEach(function(element) { element.notifyPath("obj.name", newValue); }); Polymer.dom(this.root).querySelectorAll("test-element").forEach(function(element) { element.notifyPath("obj.name", newValue); }); } }); </script> </dom-module> <test-element2></test-element2> <button>Add test-element to <em>test-element2</em> </button> <button>Add test-element to <em>body</em> </button> <script> var testElement2 = document.querySelector("test-element2"); var createTestElement = function(insertPoint) { var testElement = new TestElement(); testElement.notifyPath("obj.name", testElement2.obj.name); insertPoint.appendChild(testElement); }; document.querySelector("button:nth-of-type(2)").addEventListener("click", function() { createTestElement(Polymer.dom(document).querySelector("body")); }); document.querySelector("button").addEventListener("click", function() { createTestElement(Polymer.dom(testElement2.root)); }); </script> 
+4
source

If you decide to split your elements into your own files, you can follow this Plunker ( nazerke ) example , showing two-way data binding if one component is observing another property.

code

index.html

 <!DOCTYPE html> <html lang="en"> <head> <script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.min.js"></script> <link rel="import" href="parent-element.html"> <link rel="import" href="first-child.html"> <link rel="import" href="second-child.html"> </head> <body> <parent-element></parent-element> </body> </html> 

parent-element.html

 <link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"> <dom-module id="parent-element"> <template> <first-child prop={{value}}></first-child> <second-child feat1={{prop}}></second-child> In parent-element <h1>{{value}}</h1> </template> <script> Polymer({ is: "parent-element", properties: { value: { type: String } }, valueChanged: function() { console.log("value changed"); } }); </script> </dom-module> 

first child.html

 <link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"> <dom-module id="first-child"> <template> <p>first element.</p> <h2>{{prop}}</h2> </template> <script> Polymer({ is: "first-child", properties: { prop: { type: String, notify: true } }, ready: function() { this.prop = "property"; } }); </script> </dom-module> 

second child.html

 <link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html"> <dom-module id="second-child"> <template> <p>Second element.</p> <h2>{{feat1}}</h2> </template> <script> Polymer({ is: "second-child", properties: { feat1: { type: String, notify: true, value: "initial value" } }, ready: function() { this.addEventListener("feat1-changed", this.myAct); }, myAct: function() { console.log("feat1-changed ", this.feat1); } }); </script> </dom-module> 
+3
source

If you decide to split your elements into your own files, you can use <iron-meta> for two-way data binding as described here

Code example:

 <iron-meta key="info" value="foo/bar"></iron-meta> ... meta.byKey('info').getAttribute('value'). 

or

 document.createElement('iron-meta').byKey('info').getAttribute('value'); 

or

 <template> ... <iron-meta id="meta"></iron-meta> ... this.$.meta.byKey('info').getAttribute('value'); .... </template> 
+1
source

If you decide to split your elements into your own files, you can use <iron-localstorage> for two-way data binding as described here .

Code example:

 <dom-module id="ls-sample"> <iron-localstorage name="my-app-storage" value="{{cartoon}}" on-iron-localstorage-load-empty="initializeDefaultCartoon" ></iron-localstorage> </dom-module> <script> Polymer({ is: 'ls-sample', properties: { cartoon: { type: Object } }, // initializes default if nothing has been stored initializeDefaultCartoon: function() { this.cartoon = { name: "Mickey", hasEars: true } }, // use path set api to propagate changes to localstorage makeModifications: function() { this.set('cartoon.name', "Minions"); this.set('cartoon.hasEars', false); } }); </script> 
+1
source
 <dom-module id="test-element"> <template> <div>Hello <span>{{name}}</span></div> </template> <script> Polymer({ is: "test-element", properties: { name: String } }); </script> </dom-module> <dom-module id="test-element2"> <template> <input value="{{name::input}}"/> <test-element name="[[name]]"></test-element> </template> <script> Polymer({ is: "test-element2", properties: { name: String } }); </script> </dom-module> 
0
source

All Articles