我正在尝试理解/实现Polymer 3 Web组件中的双向属性绑定。我有以下代码:
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
class CustomInputComponent extends PolymerElement {
static get template() {
return html`
<div>
<template is="dom-repeat" items="{{ratings}}">
<input type="radio"
name="group"
id="item_{{item.id}}"
value="{{item.checked}}"
checked$="{{item.checked}}">
</template>
</div>`;
}
static get properties() {
return {
ratings: {
type: Array,
value: [
{ id: 1, checked: true },
{ id: 2, checked: false }
]
}
};
}
}
window.customElements.define('custom-input-component', CustomInputComponent);
如您所见,我已经定义了一个包含默认值列表的Array属性。此属性是我想要渲染无线电组的模型。初始状态看起来不错。但是,当我单击未选中的输入时,DOM元素无法正确更新。
我敢打赌,我错过了一些非常简单的事情......
答案 0 :(得分:4)
主要的是:
您绑定到checked
属性($=
),但我认为无线电输入不会动态更新其checked
属性。 AFAICT,checked
属性在选择输入时会发生变化。
此外,原生<input type="radio">
输入只会在选择时触发change
和input
个事件,而不会在取消选中时触发。 Polymer依赖于事件来触发数据绑定等属性效果;这意味着只有当输入上的checked
属性从false
更改为true
时,才会处理向上数据绑定(从输入到自定义元素)。实际上,一旦ratings[n].checked
变为真,它永远不会被伪造,因为Polymer无法知道这已经发生过。
顺便说一下,要对本机HTML元素TargetPlatform
constant执行双向绑定。因此,如果你确实想要捕捉选择的变化,那就像checked="{{item.checked::change}}"
。
有两种选择:
在you would also need to include an annotation for the event that the radio input fires when it is selected内使用paper-radio-button
s代替原生<input>
。这些元素在双向数据绑定方面表现良好。
在检查新项目时收听更改,并为先前选择的项目手动更新ratings[n].checked
至false
。
关于代码的更多内容
(我不认为这与您当前的问题有任何关系,但它有助于避免将来出现问题)在Polymer元素中初始化对象或数组属性的默认值时,{{3}这样每个元素实例都有自己唯一的数组或对象。 E.g:
ratings: {
type: Array,
value: function(){
return [
{ id: 1, checked: true },
{ id: 2, checked: false }
];
}
}
通常我认为,您不希望更改无线电输入的值。传统上,当提交包含无线电输入组的<form>
时,当前value
的无线电输入上的checked
被包含在表格数据中,并忽略其他无线电输入值。 paper-radio-group
。因此,而不是value="{{item.checked}}"
,而不是value="[[item.data]]"
。
所以整个事情可能就像
class CustomInputComponent extends PolymerElement {
static get properties () {
return {
ratings: {
type: Array,
value: function(){
return [
{ id: 1, checked: true, value: 'pie' },
{ id: 2, checked: false, value: 'fries' },
{ id: 3, checked: false, value: 'los dos' }
];
}
},
selected: {
// type: Number or Object, idk
// Keep track of the selected <input>
}
};
}
static get template() {
return html`
<p>do you want pie or fries?</p>
<div id="mydiv">
<template is="dom-repeat" items="{{ratings}}">
<input
type="radio"
name="testgroup"
id="[[item.id]]"
value="[[item.value]]"
checked="{{item.checked::input}}"
on-change="radioChanged"
>[[item.value]]
</input>
</template>
</div>
`;
}
radioChanged(event){
// update ratings[n].checked for selected input
// set selected input to currently selected input
}
}