2016-07-30 32 views
0

我正在嘗試使用聚合物,並且正在努力弄清楚如何以Polymer-y方式創建我的系統。使用聚合物構造列表的動態列表

我想要一個左側導航欄(左側的一列),as shown in the example app docs。出於解釋的目的,左側導航欄顯示人員列表,主要內容窗口顯示他們擁有的書籍列表。當選擇一個人時,主要內容窗口應該更新以僅顯示該人的書籍。

這兩個列表應該通過網絡查詢動態填充,並能夠通過刷新按鈕重新填充。看起來這可能會使數據綁定變得複雜,因爲這些功能不能只存在於陰影中,因爲導航欄和內容列表需要能夠進行通信。

從我查看Polymer的那一天起,導航欄(人員列表)似乎是<iron-selector>的自然人選。書的名單聽起來像<iron-list>。然而,我需要有幾本書單的例子 - 每個人都有一個例子。

我應該爲模板創建一個<book-list>自定義元素,或許在模板中使用<iron-list>?是否易於創建這些<book-list>元素來響應<iron-selector>中的選擇,因爲在查詢圖書所有者之前,我不知道如何創建它們?如何做到這一點的任何指針?

這聽起來像是一個非常基本的用例,但我仍然不太瞭解聚合物對最佳方式有任何直覺。任何幫助將非常感激。

+0

你有沒有想過使用路由器?您可以使用用戶名在欄中動態創建菜單。當用戶名被點擊時,工具導航到'/ user/'。然後在主視圖中有一個元素,然後用'USER_ID'請求用戶,然後輸出與該用戶關聯的書籍。類似於[shop demo](https://www.polymer-project.org/1.0/toolbox/case-study)的工作方式 –

回答

0

我終於得到了這個工作。作爲一個起點,我傾向於使用app-drawer-templateexample given in the docs

正如上述評論者所建議的,使用路由器最終成爲答案的一部分。令我困惑的是,我不確定如何動態更新該示例中使用的<iron-selector>以及<iron-pages>。我希望兩者都代表相同的用戶列表。我將如何保持這些同步等?

我結束了三個自定義元素。兩個是圍繞<iron-selector><iron-pages>的薄包裝。第三個是<user-provider>元素。 <user-provider>的作用是對用戶列表執行請求,並將結果公開爲其他兩個元素可以交互的變量。

<user-provider>只有一個刷新按鈕。它有一個users類型Array屬性。在ready()生命週期回調中,爲了響應點擊刷新按鈕,它更新用戶列表。請注意,reflectToAttributenotify都設置爲true,確保它確實可以將列表提供給其他元素。一個精簡版本如下所示:

<dom-module id="user-provider"> 
    <template> 
    <style> 
     :host { 
     display: block; 
     box-sizing: border-box; 
    </style> 
    <paper-fab icon="refresh" on-tap="refresh"></paper-fab> 
    </template> 

    <script> 
    Polymer({ 
     is: 'user-provider', 
     properties: { 
     users: { 
      type: Array, 
      notify: true, 
      reflectToAttribute: true 
     } 
     }, 
     refresh: function() { 
     this.refreshUsers(); 
     }, 
     refreshUsers: function() { 
     var _this = this; 
     // in reality I require a browserify module here 
     window.getUsersViaPromise() 
      .then(retrievedUsers => { 
      _this.users = retrievedUsers; 
      }); 
     }, 
     // Element Lifecycle 
     ready: function() { 
     this.users = []; 
     this.refreshUsers(); 
     } 
    }); 
    </script> 
</dom-module> 

我的<user-selector>元素將一個數組作爲參數。在這裏困住我的東西是我沒有意識到在<iron-selector>中使用dom-repeat模板有多簡單。我想我不得不在<div>或其他東西中包裝重複,此時<iron-selector>將停止工作。有了dom-repeat,我甚至可以使用我的特殊settings元素並始終將其保留在列表的底部。變量incoming對應於選定的元素。

<dom-module id="user-selector"> 
    <template> 
    <style> 
     :host { 
     display: block; 
     --app-primary-color: #4285f4; 
     --app-secondary-color: black; 
     } 
    </style> 

    <iron-selector 
     selected="{{incoming}}" 
     attr-for-selected="name" 
     class="drawer-list" 
     role="navigation"> 

     <template is="dom-repeat" items="{{users}}"> 
     <a name="view{{index}}">{{item.instanceName}}</a> 
     </template> 

     <a name="settings">Settings</a> 

    </iron-selector> 

    </template> 

    <script> 
    Polymer({ 
     is: 'user-selector', 
     properties: { 
     incoming: { 
      type: String, 
      reflectToAttribute: true, 
      notify: true 
     }, 
     users: { 
      type: Array, 
      reflectToAttribute: true 
     }, 
     } 
    }); 
    </script> 
</dom-module> 

<user-pages>是圍繞<iron-pages>薄包裝。它與<user-selector>一起工作來更新應用程序主要部分中顯示的內容。

<dom-module id="user-pages"> 
    <template> 
    <style> 
     :host { 
     display: block; 
     box-sizing: border-box; 
     } 
    </style> 

    <iron-pages role="main" selected="{{incoming}}" attr-for-selected="name"> 

     <template is="dom-repeat" items="{{users}}"> 
     <user-summary 
      name="view{{index}}" 
      username="{{item.userName}}"> 
     </user-summary> 
     </template> 

     <settings-view name="settings"></settings-view> 

    </iron-pages> 

    </template> 

    <script> 
    Polymer({ 
     is: 'user-pages', 

     properties: { 
     users: Array, 
     incoming: { 
      type: String, 
      reflectToAttribute: true, 
      notify: true 
     }, 
     } 
    }); 
    </script> 
</dom-module> 

最後,我<my-app>元素鉛垂線放在一起。

<dom-module id="my-app"> 
    <template> 
    <style> 
     :host { 
     display: block; 
     --app-primary-color: #4285f4; 
     --app-secondary-color: black; 
     } 

     app-header { 
     background-color: var(--app-primary-color); 
     color: #fff; 
     } 
     app-header paper-icon-button { 
     --paper-icon-button-ink-color: white; 
     } 

     .drawer-list { 
     margin: 0 20px; 
     } 
     .drawer-list a { 
     display: block; 
     padding: 0 16px; 
     line-height: 40px; 
     text-decoration: none; 
     color: var(--app-secondary-color); 
     } 
     .drawer-list a.iron-selected { 
     color: black; 
     font-weight: bold; 
     } 
     .drawer-list a.subroute { 
     padding-left: 32px; 
     } 
    </style> 

    <app-route 
     route="{{page}}" 
     data="{{routeData}}" 
     tail="{{subroute}}"></app-route> 

    <app-drawer-layout fullbleed> 

     <!-- Drawer content --> 
     <app-drawer> 
     <app-toolbar>My App</app-toolbar> 
     <start-app-button></start-app-button> 
     <user-provider users="{{retrievedUsers}}"></user-provider> 
     <user-selector incoming="{{page}}" users="{{retrievedUsers}}"> 
     </user-selector> 
     </app-drawer> 

     <!-- Main content --> 
     <app-header-layout has-scrolling-region> 

     <app-header condenses reveals effects="waterfall"> 
      <app-toolbar> 
      <paper-icon-button icon="menu" drawer-toggle></paper-icon-button> 
      <div title>My App</div> 
      </app-toolbar> 
     </app-header> 

     <user-pages 
      incoming="{{page}}" 
      users="{{retrievedUsers}}"> 
     </user-pages> 

     </app-header-layout> 

    </app-drawer-layout> 

    </template> 

    <script> 
    Polymer({ 
     is: 'my-app', 
     properties: { 
     page: { 
      type: String, 
      reflectToAttribute: true 
     }, 

     }, 
     observers: [ 
     '_routePageChanged(routeData.page)' 
     ], 
     _routePageChanged: function(page) { 
     this.page = page || 'view1'; 
     } 
    }); 
    </script> 
</dom-module> 

請特別注意,<user-provider>負責獲取用戶的列表中,只是通過一個變量來暴露它,讓其他兩個元素,使通過基本數據綁定獲取數據的方式。這與dom-repeat元素一起作爲<iron-selector><iron-pages>的直系子元素,一旦我開始以聚合物的方式開始思考它,讓它變得非常簡單。