【问题标题】:polymer class binding inside dom-repeat not workingdom-repeat 内的聚合物类绑定不起作用
【发布时间】:2016-12-29 10:41:15
【问题描述】:

我正在尝试将计算值绑定到 dom-repeat 模板中的元素。

<iron-selector class="dropdown-content" selected="0">
   <template is="dom-repeat" items="[[items]]">
      <div class$="item {{_itemClass(selectedItems)}}" data-value="[[item]]" on-click="_onItemClick">[[item]]</div>
   </template>
</iron-selector>

我的目标是在用户选择其中一项时更新下拉项样式。发生这种情况时,我通过将项目值推送到 selectedItems 数组来更新它。这将触发选择框的呈现,但将无法调用_itemClass(selectedItems) 表达式。

我在这里缺少什么?我在文档中读到,您必须指定将触发绑定的属性,我通过将selectedItems 添加到绑定表达式来做到这一点,但一点运气都没有。

我附加了一个带有当前行为的 sn-p。

欢迎任何帮助。

<!doctype html>
<head>
  
  <meta charset="utf-8">
  <!-- polygit -->
  <base href="https://polygit.org/components/"> <!-- saves typing! -->
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
  <link rel="import" href="iron-flex-layout/iron-flex-layout-classes.html">
  <link rel="import" href="iron-icons/iron-icons.html">
  <link rel="import" href="iron-dropdown/iron-dropdown.html">
  <link rel="import" href="iron-selector/iron-selector.html">
  <!-- style -->
  <style>
    x-example {
      width: 250px;
    }
  </style>
</head>
<body>
  
<x-example></x-example>
  
<dom-module id="x-example">
  <style include="iron-flex iron-flex-alignment"></style>
  <style>
    :host {
      position: relative;
      border: 1px solid blue;
      display: block;
    }
    
    .body {
      @apply --layout-horizontal;
    }

    .body .selection {
      border: 1px solid green;
      margin: 2px;
      flex-grow: 1
    }

    .body .selection .item {
      display: inline-block;
      margin: 2px;
      background: lightgreen;
      padding: 2px 5px;
      border: 1px solid green;
      border-radius: 4px;
      color: darkblue;
    }

    .body .selection .item .text {
      display: inline-block;
    }

    .body .selection .item iron-icon {
      width: 18px;
      cursor: pointer;
    }

    .body .dropdown {
      border: 1px solid yellow;
      margin: 2px;
      cursor: pointer;
      min-height: 40px;
    }

    .body .dropdown iron-icon {
      margin: auto;
    }

    .options iron-dropdown {
      border: 1px solid grey;
      border-radius: 6px;
      overflow: hidden;
    }

    .options .item {
      cursor: pointer;
    }

    iron-selector>* {
      padding: 8px;
      background: aqua;
    }

    .horizontal-section {
      padding: 0;
    }

    .iron-selected {
      background-color: var(--google-blue-500);
      color: white;
    }
    
  </style>
  <template>
 
        <div class="body">
            <div class="flex selection">
                <template is="dom-repeat" items="[[selectedItems]]">
                    <div class="item">
                        <div class="text">[[item]]</div>
                        <iron-icon class="dropdown-trigger" icon="icons:clear" on-click="_onRemoveItem"></iron-icon>
                    </div>
                </template>
            </div>
            <div class="dropdown" on-click="_toggleDropdown">
                <iron-icon icon="icons:arrow-drop-down"></iron-icon>
            </div>
        </div>
        <div class="options">
            <iron-dropdown auto-fit-on-attach="true" id="dropdown" horizontal-align="left" vertical-align="top">
                <iron-selector class="dropdown-content" selected="0">
                    <template is="dom-repeat" items="[[items]]">
                        <div class$="item {{_itemClass(selectedItems)}}" data-value="[[item]]" on-click="_onItemClick">[[item]]</div>
                    </template>
                </iron-selector>
            </iron-dropdown>
        </div>
    
  </template>
  <script>
    
    // only need this when both (1) in the main document and (2) on non-Chrome browsers
    addEventListener('WebComponentsReady', function() {
      
      Polymer({
        is: "x-example",
        properties: {
          items: {
            type: Array,
            value: ["One", "Two", "Three"]
          },
          selectedItems: {
            type: Array,
            value: []
          }
        },
        _toggleDropdown: function() {
          this.$.dropdown.toggle();
        },
        _onItemClick: function(e) {
          var value = e.srcElement.dataValue;
          if (this.selectedItems.indexOf(value) >= 0) {
            return;
          }
          this.push("selectedItems", value)
          this._refreshDropdown();
        },
        _refreshDropdown: function() {
          this.async(function() {
            this.$.dropdown.position();
          })
        },
        _onRemoveItem(e) {
          let index = this.selectedItems.indexOf(e.srcElement.dataValue);
          this.splice("selectedItems", index, 1);
          this._refreshDropdown();
        },
        _itemClass: function() {
          console.log("item class called")
        }
        
      });
      
    });
    
  </script>
</dom-module>
  
</body>

【问题讨论】:

    标签: binding polymer-1.0 dom-repeat


    【解决方案1】:

    您的绑定是_itemClass(selectedItems),它仅在变量 selectedItems 更改时触发,而不是在数组发生变异时触发。

    你有两个选择:

    1) 将您的绑定更改为_itemClass(selectedItems.*),这将由this.push 和其他数组变异方法触发

    2) 每次改变变量:

    this.set('selectedItems', [].concat(this.selectedItems).concat(value));
    

    herehere提供了第一个解决方案(和第二个解决方案被注释掉)的工作示例

    【讨论】:

      【解决方案2】:

      我没有测试过您的问题,但我自己也在使用类似的模式。我的猜测是 Polymer 不支持在同一标签内声明类和绑定类。

      我改用属性和属性选择器,效果和预期一样。

      你可以尝试将类更改为基于属性选择器的属性和样式吗?以下是相关代码:

      <style>
      
      .item[selected] {
        font-weight: bold;
      }
      
      </style>
      
      ...
      
      <template is="dom-repeat" items="[[items]]">
        <div class="item" selected$="[[_computeSelected]]" on-tap="_onItemTap">[[item]]</div>
      </template>
      
      
      _onItemTap: function(event) {
        const item = event.model.item;
      },
      
      _computeSelected: function(item) (
        return yourSelectionLogic ? true : false;
      }
      

      另外两个注意事项:使用点击而不是点击。它使移动触摸事件与桌面事件标准化。此外,您不需要为每个项目绑定数据值,因为当它在 dom-repeat 中触发时,它包含在点击事件中。

      【讨论】:

      • 首先,感谢您对点击事件和作为参数的数据值的提示。绑定到类属性记录在link,所以我假设这是可能的。我尝试按照您的描述进行操作,但 selected$ 属性仅在第一次迭代时计算。我希望它是动态的。因此,当我更改选择时,会计算值。这仍然不起作用。
      • 在这种情况下,您最干净的选择可能是更新 items 数组中的基础数据。这将触发新的计算。这样一来,您将拥有一个事实来源。
      • "我的猜测是 Polymer 不支持在同一个标​​签内声明类和绑定类。" 这种情况属于 compound bindings 并由聚合物。
      猜你喜欢
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-27
      • 2016-03-18
      相关资源
      最近更新 更多