Soru İçeriğe Polimer Dom Tekrarı Bağlama


Polimer 1.2.3 'de, mümkün mü dom-repeat İçeriği şablon olarak kullanmak ve sağlanan öğelere değerleri bağlamak için?

Özel öğe:

<dom-module id="modify-collection">
  <template>
    <div>
      <template is="dom-repeat" items="[[collection]]">
        <content></content>
      </template>
    </div>
  </template>
</dom-module>

Kullanımı:

<modify-collection collection="{{things}}">
  <list-item resource="[[item]]"></list-item>
</modify-collection>

Aşağıdaki kaynakları yardım almadan inceledim:

Polimer: <content> özelliklerinde değişiklik nasıl izlenir?

Polimer 1.0 şablonu

İç içe polimer elemanları arasındaki veri bağlama

https://github.com/grappendorf/grapp-template-ref

https://github.com/Trakkasure/dom-bindref

https://github.com/Polymer/polymer/issues/1852

https://github.com/Polymer/polymer/pull/2196


2016-02-03 Güncellemesi: Polimer Ekibinden(PR # 2196)Gelecekte bazı eksikliklerin giderilmesine yardımcı olmak için bunun için daha iyi destek planlanmaktadır.


18
2018-01-06 23:57


Menşei


@btelles, Aşağıda mémoire bakın. - Zachary Moshansky
Bunun için bir Polimer 2.x veya 3.x çözümü olup olmadığını merak ediyorum. - RPinel


Cevaplar:


TLDR

Çözüm 2 biraz daha ayrıntılı olsa da, en iyi şekilde çalışıyor gibi görünüyor. Ayrıca, şablonunuzun dinamik olarak seçimini de sağlar, belki de bir modelin niteliklerine göre. (Bkz. Çözüm 2: Gelişmiş Örnek)


backstory

Bu basit örnekte, gölge, gölgeli ve ışık kubbeleri arasında içerik elde etmek, ve elbette veriye bağlanma dahil olmak üzere bu basit örnekte bir şeyler oluyor.

Bu soru, bir miktar öngörü sağladı, ancak Polymer 0.5's injectBoundHtml gerçekten işe yaramazdı (Bir Polimer elemanın içinde ışık dom olarak tanımlanan şablonu kullanma). Sorun şu ki, şablonumuza innerHTML kullanarak bir elemanı kopyalamaya çalıştığımızda veri bağlarımız kayboluyor (AFAIK).

Öyleyse, şablon olmadan veri bağlama ile şablonumuzu oluşturamayız. Böylece, her iki çözüm de içeriği bir şablonda zamanın ötesine sarmaktadır; Bu, html'nin inert olmasına ve Polimer'in uygun zamanda veriye bağlanmasına neden oldu (http://www.html5rocks.com/en/tutorials/webcomponents/template/).

Her şeyi gerçekten anlamak istiyorsan Polimer okumayı tavsiye ederim. src için lib/template/dom-repeat.html, lib/template/templatizer.html, lib/annotations/annotations.html (~ 1500 satır).


Çözüm 1 -

Görmek btelle'nin cevabı aşağıda Geliştirilmiş bir çözüm için 1.

Not, bu yaklaşım neden olur dom-repeat İçeriği otomatik olarak oluşturmamak için, el ile oluşturmayı çağırıyoruz.

eleman

<dom-module id="modify-collection">
  <template>
    <div>
      <content></content>
      <template id="repeater" is="dom-repeat" items="[[collection]]"></template>
    </div>
  </template>

  <script>
    ...
    ready: function() {
      this.$.repeater.templatize(this.querySelector('#templ'));
    }
    _changeCollection: function(item) {
      this.push('collection', item);
      this.$.repeater.render();
    }
  </script>
</dom-module>

kullanım

<modify-collection collection="{{things}}">
  <template id="templ"><list-item resource="[[item]]"></list-item></template>
</modify-collection>


Çözüm 2

Bunun kullanımının 1 numaralı öğeden farklı olduğunu unutmayın. <template> bir olmalı is="dom-template" bağlıyor.

Yardımcı eleman

(Bu PR'dan biraz değiştirildi: https://github.com/Polymer/polymer/pull/2196, esasen dayalı https://github.com/grappendorf/grapp-template-ref)

!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<!--
  Portions of this code have been adapted from the `grapp-template-ref` element.

  The original copyright notices are below.
-->
<!--
MIT License
Copyright (c) 2014-2015 Dirk Grappendorf, www.grappendorf.net

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
 -->

<!--

 The `dom-ref` element is a custom `HTMLTemplateElement` type extension that
can be used to reference another template by id using the `ref` property.
`dom-bindref` accepts a `bind` property to bind an object to the referenced
template. By default the bound object can be accessed as `item`, this can be
changed using the `as` property.

Example:

```html
<template is="dom-template" id="template-bind"><span>[[item.key]]</span></template>
<template is="dom-ref" ref="template-bind" bind='{"key":"value"}'></dom-ref>
```

-->
<!-- <link rel="import" href="templatizer.html"> -->

<script>

  Polymer({

    is: 'dom-ref',
    extends: 'template',

    /**
     * Fired whenever DOM is added or removed by this template (by
     * default, rendering occurs lazily).  To force immediate rendering, call
     * `render`.
     *
     * @event dom-change
     */

    properties: {

      /**
       * Reference to another template's id.
       */
      ref: {
        type: String,
        observer: '_refChanged'
      },

      /**
       * Object to be bound to referenced template.
       */
      bind: {
        type: Object,
        observer: '_bindChanged'
      },

      /**
       * The name of the variable to add to the binding scope for the
       * element associated with a given template instance.
       */
      as: {
        type: String,
        value: 'item'
      }
    },

    behaviors: [
      Polymer.Templatizer
    ],

    ready: function() {
      this.templatize(this);
    },

    attached: function() {
      return this._stamp();
    },

    detached: function() {
      return this._removeChildren();
    },

    _refChanged: function(newRef, oldRef) {
      if (oldRef) {
        this._removeChildren();
        return this._stamp();
      }
    },

    _bindChanged: function(newBind, oldBind) {
      if (oldBind) {
        this._removeChildren();
        return this._stamp();
      }
    },

    _stamp: function() {
      var root, template, templateRoot, bind = {};
      this._parent = Polymer.dom(this).parentNode;
      root = this._parent;

      while (Polymer.dom(root).parentNode) {
        root = Polymer.dom(root).parentNode;
      }
      template = Polymer.dom(root).querySelector("template#" + this.ref);

      // Check For Light Dom Elements that may be passed to this shadow root (Useful for: `<content></content>`)
      if (!template) {
        template = root.host.querySelector("template#" + this.ref);
      }

      // Check the whole document
      if (!template) {
        template = document.querySelector("template#" + this.ref);
      }
      bind[this.as] = this.bind;

      // templateRoot = template.stamp(bind).root;
      // Use this method until this lands: https://github.com/Polymer/polymer/pull/1889
      templateRoot = (new template.ctor(bind, template)).root;
      this._children = Array.prototype.slice.call(templateRoot.childNodes);
      return Polymer.dom(this._parent).insertBefore(templateRoot, this);
    },

    _removeChildren: function() {
      var child, i, len, ref, results;
      if (this._children) {
        ref = this._children;
        results = [];
        for (i = 0, len = ref.length; i < len; i++) {
          child = ref[i];
          results.push(Polymer.dom(this._parent).removeChild(child));
        }
        return results;
      }
    }

  });

</script>

eleman

<dom-module id="modify-collection">
  <template>
    <div>
      <content></content>
      <template is="dom-repeat" items="[[collection]]">
          <template is="dom-ref" bind="[[item]]" ref="templ"></template>
      </template>
    </div>
  </template>
</dom-module>

kullanım

<modify-collection collection="{{things}}">
  <template id="templ" is="dom-template"><list-item resource="[[item]]"></list-item></template>
</modify-collection>

Gelişmiş Eleman

Kullanım yukarıdan değişmez.

Burada yaptığımız şey, bizim elemanımıza aktarılan bir şablonun (örneğimizde bir bindirme ile) sarılmasına izin veren bir dolaylılık seviyesi getirmektir.

<dom-module id="modify-collection">
  <template>
    <div>
      <content></content>
      <template id="wrapper" is="dom-template">
        <div class="overlay">
          <template is="dom-ref" bind="[[item]]" ref="templ"></template>
        </div>
      </template>

      <template is="dom-repeat" items="[[collection]]">
        <template is="dom-ref" bind="[[item]]" ref="[[_templateRef(_overlayMode)]]"></template>
      </template>
    </div>
  </template>

  <script>
    ...
    properties: {
      _overlayMode: {
        type: Boolean,
        value: false
      }
    },
    _templateRef: function(overlayMode) {
      return overlayMode ? 'wrapper' : 'templ';
    }
  </script>
</dom-module>

17
2018-01-12 18:55



Harika! . . - Günter Zöchbauer
sadece özveri için aşağı çekildi :) - Thoran
En üst seviyenin iç seviyelerini tanımladığı çoklu seviyelerde bunun mümkün olup olmadığını anlamaya çalışıyorum, fakat ikinci seviye yuvalama şu an beni yeniyor: codepen.io/diddledan/pen/bBrxZR - Daniel Llewellyn


FWIW, aşağıdaki çözümlerin yanı sıra çözüm 1'e benziyor ve ona bildirim yollarını (ve otomatik bağlama / değiştirme, vb.) Ekler:

<dom-module id="i-me">
  <template>
    <content></content>
    <template is="dom-repeat" id="repeater" items="[[collection]]"></template>
  </template>
  <script>
    Polymer({
      is: 'i-me',
      properties: {
        collection: {
          type: Array,
          value: [
            {id: 1, name: 'a'},
            {id: 2, name: 'b'}
          ],
          notify: true
        }
      },
      ready() {
        this.$.repeater.templatize(this.querySelector('#templ'));
        Polymer.Bind.prepareModel(this.$.repeater);
        Polymer.Base.prepareModelNotifyPath(this.$.repeater);
      }
    });
  </script>
</dom-module>

O zaman şunu kullan:

<i-me>
  <template id="templ">
  <p><span>[[item.id]]</span>: <span>[[item.name]]</span></p>
  </template>
</i-me>

6
2018-01-12 20:44



Bu temiz bir çözümdür. Teşekkürler! - pitachip
İçeriği dışarıdan yeniden düzenlenecek şekilde biçimlendirmenin herhangi bir yolu var mı? <i-me>? - Nicholas Kyriakides


Örnek olarak demir liste öğesini kullanın. İşte geçen şablon elemanını kapıyor https://github.com/PolymerElements/iron-list/blob/9909b73a00ecc91fb957232f7bc66b59435d66ad/iron-list.html#L830. Templatizer mixin, geçirilen şablona bağlanmayı uygulamak için AFAIK kullanılır (aynı zamanda <template is="dom-repeat">)


2
2018-01-07 07:53



Tavsiyem için teşekkürler Gunter, problemin karmaşıklığı nedeniyle daha ayrıntılı bir cevap yazmayı tercih etsem de. - Zachary Moshansky