简体   繁体   English

聚合物3:如何实现无线电输入的双向数据绑定

[英]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">输入只会在选择它们时触发它们的changeinput事件,而不是在取消选择它们时。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM