7

ツリー ビューやマルチ リスト ビュー (2 つのリスト間で項目を移動する) など、JSON オブジェクト コレクションをレンダリングする一般的な Web コンポーネントを構築しようとしています。個々のアイテムのプレゼンテーションを含むテンプレートが再利用のためにコンポーネントに渡される、iron-list で使用されるパターンをコピーしたいと思います。

たとえば、次の Web コンポーネント テンプレートがあるとします。

<dom-module id="intworkspace-tree">  
  <template>
    <style include="iron-flex iron-flex-alignment">

      paper-icon-item {
        --paper-item-min-height: var(--intworkspace-tree-margin,30px);
        --paper-item-icon-width : var(--intworkspace-tree-margin,30px);
      }

      paper-icon-item:focus::before,
      paper-icon-item:focus::after {
        color: inherit;
        opacity: 0;
      }

     .node {
        margin-left: var(--intworkspace-tree-margin,30px);;
      }
    </style>

    <slot id="labelView"></slot>

    <template id="nodeView">
      <div class="layout vertical">
      <paper-icon-item on-tap="nodeSelected">
        <iron-icon icon="expand-less" slot="item-icon" hidden$="[[!hasNodes(node)]]"></iron-icon>
        <!-- label goes here-->
      </paper-icon-item>

      <iron-collapse class="node" opened hidden$="[[!hasNodes(node)]]">
        <intworkspace-tree tree="[[node.nodes]]" embedded></intworkspace-tree>
      </iron-collapse>
      </div>
  </template>

  </template>
	...
  </dom-module>

そしてこの使用法:

 <intworkspace-tree tree="{{testTree}}">
      <template><paper-item-body>[[node.name]]</paper-item-body>  </template>
  </intworkspace-tree>
  
Web コンポーネントのテンプレートとスロットを介して提供されるテンプレートを組み合わせて、不透明な JSON オブジェクトをレンダリングする階層で JSON ツリー配列をレンダリングしたいと思います。これまでのところ、テンプレートを組み合わせる 2 つの方法を特定しました。

  1. Polymer.Templatize.templatize API を使用してテンプレートを読み込み、新しいインスタンスを作成/スタンプし、DOM API を使用してそれらを一緒に追加し、Web コンポーネントのシャドウ DOM に追加します。

  2. テンプレートのコンテンツにアクセスし、それらを結合し、新しいテンプレートを作成してインポートし、必要に応じて複製します。

多くの逆境の後、#1 をうまく実装できましたが、#2 を実装できませんでした。それが私の質問の動機です。#2 は、結果としてスタンプされたインスタンスをマージするよりもテンプレートを一度マージする方が簡単であり、このアプローチが dom-repeat のようなネストされたテンプレートを再利用できる唯一の方法であるように思われるため、より魅力的です。

私の主な障害は、Polymer またはおそらくそのポリフィルが読み込まれると、テンプレートが不透明になり、Polymer のテンプレート化機能でしか利用できないことです。たとえば、次のコードは Polymer をインポートしなくても問題なく動作します。

<template>
  <div>Template Contents</div>
</template>
<div>
  Template Test
</div>
  <script>
  let template = document.querySelector("template");
  let clone = document.importNode(template.content,true);
  document.querySelector("div").appendChild(clone);
  </script>

Polymer の外部では、template.content DOMFragment に子があり、innerHTML が設定されています。ただし、Polymer が使用されると、template.content には子がなく、innerHTML は空になります。これにより、DOM API を使用して、使用可能なテンプレートをブレンドする新しいテンプレートを作成することができなくなります。

let newTemplate = document.createElement("template");
newTemplate.content = ... // combine #labelView > template.content with #nodeView.content 
let nodeView = document.importNode(newTemplate.content,true);
nodeView.tree=...

おそらく、設計上、標準の HTML メカニズムを使用してテンプレートをインポートすることがうまくいかなかったのでしょう。Polymer で実行時にテンプレートを動的に作成/マージする別の方法はありますか? 繰り返しますが、私の主な動機は、すべての機能を再実装することなく、テンプレートにネストされた dom-if および dom-repeat Web コンポーネントを再利用したいということです。

4

2 に答える 2