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

时间:2018-06-15 16:13:19

标签: javascript polymer web-component polymer-3.x

我正在尝试理解/实现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元素无法正确更新。

First element is checked although I clicked the second one and the browser also displays that.

我敢打赌,我错过了一些非常简单的事情......

1 个答案:

答案 0 :(得分:4)

主要的是:

  • 您绑定到checked属性($=),但我认为无线电输入不会动态更新其checked属性。 AFAICT,checked 属性在选择输入时会发生变化。

  • 此外,原生<input type="radio">输入只会在选择时触发changeinput个事件,而不会在取消选中时触发。 Polymer依赖于事件来触发数据绑定等属性效果;这意味着只有当输入上的checked属性从false更改为true时,才会处理向上数据绑定(从输入到自定义元素)。实际上,一旦ratings[n].checked变为真,它永远不会被伪造,因为Polymer无法知道这已经发生过。

    顺便说一下,要对本机HTML元素TargetPlatform constant执行双向绑定。因此,如果你确实想要捕捉选择的变化,那就像checked="{{item.checked::change}}"

有两种选择:

关于代码的更多内容

  • (我不认为这与您当前的问题有任何关系,但它有助于避免将来出现问题)在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
  }
}