2016-12-29 54 views
1

我试图将计算值绑定到dom-repeat模板中的元素。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添加到绑定表达式中而没有运气。

我附带了一个片段与当前的行为。

任何帮助将受到欢迎。

<!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>

回答

0

我没有测试过您的问题,但我使用了类似的模式自己。我的猜测是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; 
} 

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

+0

首先,感谢您提供关于tap事件和作为参数的数据值的提示。 绑定到类属性被记录[链接](https://www.polymer-project.org/1.0/docs/devguide/data-binding#compound-bindings),所以我假设这是可能的。 我试图按照你所描述的方式去做,但'选择的$'属性只在第一次迭代时计算。我希望它是动态的。因此,当我改变选择时,值被计算。这仍然不起作用。 –

+0

在这种情况下,您最干净的选项可能是更新项目数组中的基础数据。这将触发一个新的计算。这样,你就会有一个真相来源。 – Kristfal

+1

“_我猜测聚合物不支持在同一个标​​记中声明一个类和一个绑定类。” 这个例子属于[复合绑定](https://www.polymer-project.org/1.0/docs/devguide/data-binding#化合物结合),并受Polymer支持。 –

0

你的绑定是_itemClass(selectedItems)它只在变量selectedItems发生变化时触发,而不是在数组发生变化时触发。

你有两个选择:

1)要么改变你的结合_itemClass(selectedItems.*),将由this.push和其他阵列变异方法

2)每次更改变量被触发:

this.set('selectedItems', [].concat(this.selectedItems).concat(value)); 
与第一溶液(和第二溶液注释掉)

一个工作例子可here