Polymer 3:如何为无线电输入实现双向数据绑定
Polymer 3: How to implement two way data binding for radio input
我正在尝试 understand/implement 在 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);
如您所见,我定义了一个包含默认值列表的数组 属性。这个 属性 是我要从中渲染单选组的模型。初始状态看起来不错。但是当我点击未选中的输入时,DOM 元素没有正确更新。
我敢打赌我错过了一些非常简单的东西...
主要有:
您正在绑定到 checked
属性 ($=
),但我认为无线电输入不会动态更新其 checked
属性。 AFAICT,checked
属性 是选择输入时发生的变化。
此外,原生 <input type="radio">
输入只会在它们被选中时触发它们的 change
和 input
事件,而不是在它们被取消选择时。 Polymer 依靠事件来触发 属性 数据绑定等效果;这意味着只有当输入上的 checked
属性 从 false
变为 true
时,才会处理向上的数据绑定(从输入到您的自定义元素)。实际上,一旦 ratings[n].checked
变为真,它就永远不会变为假,因为 Polymer 无法知道这已经发生。
顺便说一下,要对原生 HTML 元素执行双向绑定,you would also need to include an annotation for the event that the radio input fires when it is selected。所以如果你确实想捕捉选择的变化,它会像 checked="{{item.checked::change}}"
.
几个选项:
使用 paper-radio-button
s inside a paper-radio-group
而不是原生的 <input>
。这些元素对于双向数据绑定表现良好。
选中新项目时监听变化,并手动更新ratings[n].checked
到false
之前选择的项目。
关于您的代码的更多信息
(我不认为这与您当前的问题有任何关系,但它有助于避免将来的问题)在初始化对象或数组的默认值时 属性一个 Polymer 元素,remember to use a function 这样每个元素实例都有自己唯一的数组或对象。例如:
ratings: {
type: Array,
value: function(){
return [
{ id: 1, checked: true },
{ id: 2, checked: false }
];
}
}
通常我认为,您不会想要更改无线电输入的值。按照惯例,当提交包含单选输入组的 <form>
时,当前为 checked
的单选输入上的 value
将包含在表单数据中,而忽略其他单选输入值. Here's an example on W3Schools。所以不是 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
}
}
我正在尝试 understand/implement 在 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);
如您所见,我定义了一个包含默认值列表的数组 属性。这个 属性 是我要从中渲染单选组的模型。初始状态看起来不错。但是当我点击未选中的输入时,DOM 元素没有正确更新。
我敢打赌我错过了一些非常简单的东西...
主要有:
您正在绑定到
checked
属性 ($=
),但我认为无线电输入不会动态更新其checked
属性。 AFAICT,checked
属性 是选择输入时发生的变化。此外,原生
<input type="radio">
输入只会在它们被选中时触发它们的change
和input
事件,而不是在它们被取消选择时。 Polymer 依靠事件来触发 属性 数据绑定等效果;这意味着只有当输入上的checked
属性 从false
变为true
时,才会处理向上的数据绑定(从输入到您的自定义元素)。实际上,一旦ratings[n].checked
变为真,它就永远不会变为假,因为 Polymer 无法知道这已经发生。顺便说一下,要对原生 HTML 元素执行双向绑定,you would also need to include an annotation for the event that the radio input fires when it is selected。所以如果你确实想捕捉选择的变化,它会像
checked="{{item.checked::change}}"
.
几个选项:
使用
paper-radio-button
s inside apaper-radio-group
而不是原生的<input>
。这些元素对于双向数据绑定表现良好。选中新项目时监听变化,并手动更新
ratings[n].checked
到false
之前选择的项目。
关于您的代码的更多信息
(我不认为这与您当前的问题有任何关系,但它有助于避免将来的问题)在初始化对象或数组的默认值时 属性一个 Polymer 元素,remember to use a function 这样每个元素实例都有自己唯一的数组或对象。例如:
ratings: { type: Array, value: function(){ return [ { id: 1, checked: true }, { id: 2, checked: false } ]; } }
通常我认为,您不会想要更改无线电输入的值。按照惯例,当提交包含单选输入组的
<form>
时,当前为checked
的单选输入上的value
将包含在表单数据中,而忽略其他单选输入值. Here's an example on W3Schools。所以不是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
}
}