[英]Polymer 3: How to implement two way data binding for radio input
I'm trying to understand/implement two way attribute binding in a Polymer 3 web component. 我正在尝试理解/实现Polymer 3 Web组件中的双向属性绑定。 I've got the following code:
我有以下代码:
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);
As you can see, I have defined a Array property containing a default list of values. 如您所见,我已经定义了一个包含默认值列表的Array属性。 This property is a model from which I want to render a radio group.
此属性是我想要渲染无线电组的模型。 The initial state looks good.
初始状态看起来不错。 But when I click on the unchecked input, the DOM elements don't update correctly.
但是,当我单击未选中的输入时,DOM元素无法正确更新。
I'd bet I'm missing something really simple... 我敢打赌,我错过了一些非常简单的事情......
The main things are: 主要的是:
You are binding to the checked
attribute ( $=
), however I don't think radio inputs dynamically update their checked
attribute. 您绑定到
checked
属性( $=
),但我不认为无线电输入会动态更新其已checked
属性。 AFAICT, the checked
property is what changes when the input gets selected. AFAICT,
checked
属性是选择输入时的更改。
Also, native <input type="radio">
inputs will only fire their change
and input
events when they are selected, not when they are de-selected. 此外,原生
<input type="radio">
输入只会在选择它们时触发它们的change
和input
事件,而不是在取消选择它们时。 Polymer relies on events to trigger property effects like data bindings; Polymer依赖于事件来触发数据绑定等属性效果; this means that an upwards data binding (from the input to your custom element) will only get processed when the
checked
property on an input changes from false
to true
. 这意味着只有当输入上的
checked
属性从false
变为true
时,才会处理向上数据绑定(从输入到自定义元素)。 Effectively, once ratings[n].checked
becomes true, it will never be made false because Polymer has no way to know that this has occurred. 实际上,一旦
ratings[n].checked
变为true,它将永远不会被伪造,因为Polymer无法知道这已经发生了。
Incidentally, to perform two-way binding on a native HTML element, you would also need to include an annotation for the event that the radio input fires when it is selected . 顺便提一下,要对本机HTML元素执行双向绑定, 您还需要为选中时无线电输入触发的事件添加注释 。 So if you did want to capture the changes on selection, it'd be something like
checked="{{item.checked::change}}"
. 因此,如果您确实想要捕获选择上的更改,那就像
checked="{{item.checked::change}}"
。
A couple of options: 有两种选择:
Use paper-radio-button
s inside a paper-radio-group
instead of native <input>
s. 在
paper-radio-group
使用paper-radio-button
而不是本机<input>
。 These elements behave well for two-way data binding. 这些元素对于双向数据绑定表现良好。
Listen for the change when a new item gets checked, and manually update ratings[n].checked
to false
for the previously selected item. 在检查新项目时监听更改,并手动将先前所选项目的
ratings[n].checked
更新为false
。
A couple more things about your code 关于代码的更多内容
(I don't think this is anything to do with your current problem, but it will help avoid future problems) when initializing a default value for an object or array property in a Polymer element, remember to use a function so that each element instance gets its own unique array or object. (我不认为这与你当前的问题有什么关系,但它有助于避免将来的问题)在Polymer元素中初始化对象或数组属性的默认值时, 记得使用一个函数使每个元素实例获得自己独特的数组或对象。 Eg:
例如:
ratings: { type: Array, value: function(){ return [ { id: 1, checked: true }, { id: 2, checked: false } ]; } }
Normally I think, you wouldn't want to change the values of your radio inputs. 通常我认为,您不希望更改无线电输入的值 。 Conventionally, when the
<form>
containing a radio input group is submitted, the value
on the radio input that is currently checked
gets included with the form data, and the other radio input values are ignored. 传统上,当提交包含无线电输入组的
<form>
时,当前checked
的无线电输入上的value
被包括在表格数据中,并且忽略其他无线电输入值。 Here's an example on W3Schools . 这是W3Schools的一个例子 。 So instead of
value="{{item.checked}}"
, something like value="[[item.data]]"
. 因此,而不是
value="{{item.checked}}"
,类似于value="[[item.data]]"
。
So the whole thing might be something like 所以整个事情可能就像
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
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.