首页 文章

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

提问于
浏览
3

我正在尝试理解/实现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 回答

  • 4

    主要的是:

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

    • 此外,原生 <input type="radio"> 输入只会在选择它们时触发它们的 changeinput 事件,而不是在它们被取消选中时触发 . 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-group中使用paper-radio-buttons而不是原生 <input> . 这些元素对于双向数据绑定表现良好 .

    • 在检查新项目时监听更改,并为先前选定的项目手动更新 ratings[n].checkedfalse .

    关于代码的更多内容

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

相关问题