使用 polymer 1.0 在两个 Polymer 元素之间进行数据绑定
Data binding between two Polymer elements using polymer 1.0
问题
In the below example, how do I bind the obj.name
variable of the <input>
field in <test-element2>
to <test-element>
?
背景:
下面是我的代码。我有两个聚合物元件。 test-element
将数据绑定到 obj.name
。 test-element2
有一个输入字段,由函数 objChanged
观察。无论我在输入字段中更改什么值,它都会更改并打印在 test-element2
中,但更改不会反映在 test-element
中。任何机构都可以帮助获得反映到 test-element1
的价值吗?当文本更改时,我有一个使用 this.fire("object-change")
的解决方案,但我正在寻找一个不使用事件侦听器的解决方案。
还有一件事是我需要从脚本创建一个元素,它不能在 HTML DOM.
中硬编码
代码:
<!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>
<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>
如果在 test-element2
的 <template>
中包含 <test-element>
,则可以避免使用事件侦听器或观察器。以这种方式 test-element2
为您处理 input
和 <test-element>
之间的数据绑定。
下面是一个实时工作示例,它维护了您在元素中设置的 obj
属性。
<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>
目前,命令式数据绑定 在 <template is="dom-bind">
之外的 Polymer 1.0 中不受支持。
我建议像下面的示例一样设置观察者或调整您的要求以在 test-element2
中包含 <test-element>
。
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>
如果您选择将元素分解到它们自己的文件中,您可以按照 this Plunker example (by nazerke) 通过让一个组件观察另一个组件 属性 来演示 two-way 数据绑定。
代码
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>
如果您选择将元素分解到它们自己的文件中,您可以使用 <iron-meta>
进行双向数据绑定 as described here:
示例代码:
<iron-meta key="info" value="foo/bar"></iron-meta>
...
meta.byKey('info').getAttribute('value').
或
document.createElement('iron-meta').byKey('info').getAttribute('value');
或
<template>
...
<iron-meta id="meta"></iron-meta>
...
this.$.meta.byKey('info').getAttribute('value');
....
</template>
如果您选择将元素分解到它们自己的文件中,您可以使用 <iron-localstorage>
进行双向数据绑定 as described here。
示例代码:
<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>
问题
In the below example, how do I bind the
obj.name
variable of the<input>
field in<test-element2>
to<test-element>
?
背景:
下面是我的代码。我有两个聚合物元件。 test-element
将数据绑定到 obj.name
。 test-element2
有一个输入字段,由函数 objChanged
观察。无论我在输入字段中更改什么值,它都会更改并打印在 test-element2
中,但更改不会反映在 test-element
中。任何机构都可以帮助获得反映到 test-element1
的价值吗?当文本更改时,我有一个使用 this.fire("object-change")
的解决方案,但我正在寻找一个不使用事件侦听器的解决方案。
还有一件事是我需要从脚本创建一个元素,它不能在 HTML DOM.
中硬编码代码:
<!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>
<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>
如果在 test-element2
的 <template>
中包含 <test-element>
,则可以避免使用事件侦听器或观察器。以这种方式 test-element2
为您处理 input
和 <test-element>
之间的数据绑定。
下面是一个实时工作示例,它维护了您在元素中设置的 obj
属性。
<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>
目前,命令式数据绑定 在 <template is="dom-bind">
之外的 Polymer 1.0 中不受支持。
我建议像下面的示例一样设置观察者或调整您的要求以在 test-element2
中包含 <test-element>
。
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>
如果您选择将元素分解到它们自己的文件中,您可以按照 this Plunker example (by nazerke) 通过让一个组件观察另一个组件 属性 来演示 two-way 数据绑定。
代码
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>
如果您选择将元素分解到它们自己的文件中,您可以使用 <iron-meta>
进行双向数据绑定 as described here:
示例代码:
<iron-meta key="info" value="foo/bar"></iron-meta>
...
meta.byKey('info').getAttribute('value').
或
document.createElement('iron-meta').byKey('info').getAttribute('value');
或
<template>
...
<iron-meta id="meta"></iron-meta>
...
this.$.meta.byKey('info').getAttribute('value');
....
</template>
如果您选择将元素分解到它们自己的文件中,您可以使用 <iron-localstorage>
进行双向数据绑定 as described here。
示例代码:
<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>