2016-12-29 71 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