Polymer :: Unable to target elements inside dom-repeat when using iron-ajax导入数据

Polymer :: Unable to target elements inside dom-repeat when using iron-ajax to import data

如果数据被硬编码为 属性 值,我可以在 dom-repeat 中定位元素。但是使用iron-ajax导入数据时,this.$$(selector) returns null.

自定义元素

<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-collapse/iron-collapse.html"/>
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html"/>
<link rel="import" href="../../bower_components/polymer-sortablejs/polymer-sortablejs.html"/>

<dom-module id="sortable-math">

  <template>
    <style>
      :host {
        display: block;
      }

      .math {
        display: block;
        padding: 20px 0;
        border-bottom: 1px solid #cccccc;
      }

      .total {
        border-top: 1px solid #cccccc;
      }
    </style>

    <h1>Math +</h1>

    <div id="empty-div"></div>

    <iron-ajax
        auto
        id="numbersDataRequest"
        url="../data/numbers.json"
        handle-as="json"
        on-response="numbersDataResponse">
    </iron-ajax>

    <div>
      <sortable-js>
        <template is="dom-repeat" items="{{numbersData}}">
          <div id="math-{{index}}" class="math">
            <table>
              <tr>
                <td class="givenNumber" on-click="toggle" toggle-id$="{{index}}">
                  {{item.givenNumber}}
                </td>
              </tr>
              <tr>
                <td class="toAdd">
                  + {{item.toAdd}}
                </td>
              </tr>
              <tr>
                <td id="total-{{index}}" class="total">?</td>
                <td></td>
              </tr>
            </table>

            <iron-collapse id$="collapsible-{{index}}">
              <div>Hint</div>
            </iron-collapse>
          </div>
        </template>
      </sortable-js>

  </div>

  </template>

  <script>
    Polymer({
      is: 'sortable-math',

      properties: {
        numbersData: {
          type: Array
        }
      },

      ready: function() {
        console.log(this.$$('#empty-div'));
      },

      _onSort: function(evt){
        console.log('sorted');
      },

      /*
      //Not working either

      attached: function(){
        this.async(function() {
          this.$$('#empty-div').innerHTML = 'Empty no more.'; //This works.
          console.log(this.$$('#math-1')); //Returns null
        });
      },

      */

      toggle: function (e, detail, sender) {
        var target = Polymer.dom(e).rootTarget.getAttribute('toggle-id'),
            selector = '#collapsible-' + target;
        this.$$(selector).toggle();
        console.log(this.$$('#math-1')); 
      },

      numbersDataResponse: function (data) {
        //console.log('numbersDataResponse');
        this.numbersData = data.detail.response;
        this.$$('#empty-div').innerHTML = 'Empty no more.'; //This works.

        //Attempt to target element created with dom-repeat
        console.log(this.$$('#math-0')); //Returns null
        console.log(this.$$('#math-0 #total-0')); //Returns null
        console.log(this.$$('#math-0 .total')); //Returns null
      }
    });

    var targetEl = function(ref, selector){
      return Polymer.dom(ref).querySelector(selector);
    }



  </script>
</dom-module>

JSON

[
  {
    "givenNumber": "3",
    "toAdd": "2"
  },
  {
    "givenNumber": "?",
    "toAdd": "5"
  },
  {
    "givenNumber": "?",
    "toAdd": "10"
  },
  {
    "givenNumber": "?",
    "toAdd": "7"
  }
]

附加信息

我想做什么:

  1. 获取 #math-0 .givenNumber 的内容 (3)
  2. 获取#math-0 .toAdd的内容:(2)
  3. 计算总数 (5) 并将其附加到 #math-1 .givenNumber
  4. 获取#math-1 .givenNumber的内容:(5)
  5. 获取#math-1 .toAdd的内容:(5)
  6. 计算总数 (10) 并将其附加到 #math-2 .givenNumber

等等...

无计算查看

计算后查看

谢谢!

您在转发器有机会标记它们之前查询转发器的项目,这导致 null。您可以等到使用 Polymer.RenderStatus.afterNextRender() 进行下一次渲染之后再查询项目:

Polymer.RenderStatus.afterNextRender(this, () => {
  console.log('math-0 (after render)', this.$$('#math-0'));
});

...或者你可以等到当前微任务结束(包括模板转发器渲染):

this.async(() => {
  console.log('math-0 (after microtask)', this.$$('#math-0'))
});

<head>
  <base href="https://polygit.org/polymer+1.7.0/polymer-sortablejs+SortableJS+:master/Sortable+RubaXa+:master/components/">
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
  <link rel="import" href="polymer/polymer.html">
  <link rel="import" href="iron-ajax/iron-ajax.html">
  <link rel="import" href="polymer-sortablejs/polymer-sortablejs.html">
</head>
<body>
  <x-foo></x-foo>

  <dom-module id="x-foo">
    <template>
      <style>
        :host {
          font-family: Roboto, sans-serif;
        }
        .item {
          margin: 20px;
        }
      </style>
      <iron-ajax url="https://jsonplaceholder.typicode.com/posts"
                 on-response="_onResponse"
                 auto></iron-ajax>
      <sortable-js>
        <template is="dom-repeat" items="[[items]]">
          <div class="item" id$="item-{{index}}">{{item.title}}</div>
        </template>
      </sortable-js>
    </template>
    <script>
      HTMLImports.whenReady(function() {
        Polymer({
          is: 'x-foo',
          _onResponse: function(e) {
            this.items = e.detail.response;

            // The template repeater has not rendered its items yet, so #item-1 would
            // not yet exist yet for us to query here.
            console.log('item-1 (before render)', this.$$('#item-1'));

            // We can use Polymer.RenderStatus.afterNextRender to explicitly wait until
            // the next render event before checking for #item-1.
            Polymer.RenderStatus.afterNextRender(this, () => console.log('item-1 (after render)', this.$$('#item-1')));

            // Alternatively, we can wait until the end of the current microtask (which
            // includes rendering the template repeater), before checking for #item-1.
            this.async(() => console.log('item-1 (after microtask)', this.$$('#item-1')));
          }
        });
      });
    </script>
  </dom-module>
</body>

codepen

由于dom-repeat绑定需要时间,所以调用后直接设置参数会有时间差,建议稍等再调用就可以了

英文不好,希望你看懂,谢谢

jsbin