在另一个自定义标签内动态创建聚合元素

6
需要在另一个聚合元素的脚本中动态创建一个名为 offices-list 的聚合元素,如下所示:
<dom-module id="contacts-tag"> 
    <template>
     <iron-ajax ... on-response = "handleResponse"></iron-ajax>
</template> 
 <script>
    Polymer({
        is: "contacts-tag",  

        handleResponse: function(request){
            var response = request.detail.response;
            this.officesRegions = response.officesRegions;  
            this.officesCities = response.officesCities;    

           var dynamicEl = document.createElement("offices-list");
           dynamicEl.setAttribute("regions", this.officesRegions);
           dynamicEl.setAttribute("cities", this.officesCities);
           document.body.appendChild(dynamicEl); 

        }
       });
</script></dom-module>

然而,一旦到达"document.createElement("offices-list");",这个新标签里的元素就开始渲染了,并且它的on ready方法已经被调用,而我本来希望它们是在我设置属性后发生的。我该怎么办?
编辑:看起来问题的性质不同。我正在将对象设置为属性,而"offices-list"标签没有识别它们,因此不能访问它或循环遍历它。那么,我的问题会变成"如何绑定对象?"

如果您想要等待元素添加后再进行渲染,则可以在attached 回调函数中实现,那么在 ready 回调函数中您会做什么呢? - Ümit
即使我将所有内容都移动到 ready to on attached 上,我仍然遇到本地 DOM 立即被渲染的问题。本地 DOM 中的元素需要属性才能正确渲染,但由于属性是在 createElement 之后添加的,所以我无法控制它从被渲染。正如我在问题中所说的那样,问题在于它不等待实际附加,而是在 createElement 后立即渲染,而无需等待属性。 - Nazerke
3个回答

11

我认为正确的答案是-这取决于你想要实现什么。

如果您想要强制性地进行数据绑定,即您希望动态地将类似以下内容添加到模板中,

<offices-list offices-regions="{{regions}}"
              offices-cities="{{cities}}">
              </offices-list>

由于Polymer 1.0不支持命令式数据绑定,所以你现在运气不太好

如果你只是想将参数(而不是数据绑定)传递到动态创建的元素中,el.setAttribute()el.myAttribute = this.myAttribute都可以。

既然你正在使用Polymer,我认为你应该尝试在框架内(在Polymer模板实例内部)包含DOM操作,而不是直接添加到document.body中,就像这样。

<dom-module id="contacts-tag"> 
  <template>
     <iron-ajax ... on-response="handleResponse"></iron-ajax>
     <div id="insertion_point"></div>
  </template> 
  <script>
    Polymer({
      is: "contacts-tag",
      handleResponse: function(request) {
        ...
        Polymer.dom(this.$.insertion_point).appendChild(dynamicEl);
      }
    });
  </script>
</dom-module>

最后,如果您的意图仅在于在ajax请求完成后简单地显示一个<contacts-tag>,我认为您可以以声明方式实现此目的。

<dom-module id="contacts-tag"> 
  <template>
     <iron-ajax ... on-response="handleResponse"></iron-ajax>

     <template is="dom-if" if="{{_unveilOfficesListWhenReady}}">
       <offices-list offices-regions="{{_regions}}"
                     offices-cities="{{_cities}}">
       </offices-list>
     </template>
  </template> 
  <script>
    Polymer({
      is: "contacts-tag",
      properties: {
        _regions: String,
        _cities: String,
        _unveilOfficesListWhenReady: { type: Boolean, value: false }
      },
      handleResponse: function(request) {
        var response = request.detail.response;
        this._regions = response.officesRegions;  
        this._cities = response.officesCities;
        this._unveilOfficesListWhenReady = true;
      }
    });
  </script>
</dom-module>

不需要动态元素。


很好的发现:“Polymer.dom(this.$.insertion_point).appendChild(dynamicEl);”我已经在我的代码中进行了更正,忘记在这里做同样的事情。Umit的回复对我有用,感谢您的解释。 - Nazerke
嗯,如果是这样的话,那意味着你没有在 <offices-list> 元素内的 properties 对象中公开任何属性,所以我不确定为什么你会想要特别为此创建一个新的 Web 组件... 但无论怎样,只要能工作就行。 - zerodevx

8
您不应该使用setAttribute,而应该直接设置相应的属性。
var dynamicEl = document.createElement("offices-list");
dynamicEl.regions = this.officesRegions;    
dynamicEl.cities = this.officesCities;
document.body.appendChild(dynamicEl); 

1
对于属性 (HTMLElement属性)的设置,您需要使用setAttribute。例如:dynamicEl.setAttribute('regions', this.officesRegions); - tomloprod

1

您可以使用 Polymer 团队提供的 DOM API

Polymer.dom(parent).appendChild(polymerChild)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接