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"
}
]
附加信息
我想做什么:
- 获取
#math-0 .givenNumber
的内容 (3
)
- 获取
#math-0 .toAdd
的内容:(2
)
- 计算总数 (
5
) 并将其附加到 #math-1 .givenNumber
- 获取
#math-1 .givenNumber
的内容:(5
)
- 获取
#math-1 .toAdd
的内容:(5
)
- 计算总数 (
10
) 并将其附加到 #math-2 .givenNumber
等等...
无计算查看
- 3 + 2 = ?
- ? + 5 = ?
- ? + 10 = ?
- ? + 7 = ?
计算后查看
- 3 + 2 = 5
- 5 + 5 = 10
- 10 + 10 = 20
- 20 + 7 = 27
谢谢!
您在转发器有机会标记它们之前查询转发器的项目,这导致 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>
由于dom-repeat绑定需要时间,所以调用后直接设置参数会有时间差,建议稍等再调用就可以了
英文不好,希望你看懂,谢谢
如果数据被硬编码为 属性 值,我可以在 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"
}
]
附加信息
我想做什么:
- 获取
#math-0 .givenNumber
的内容 (3
) - 获取
#math-0 .toAdd
的内容:(2
) - 计算总数 (
5
) 并将其附加到#math-1 .givenNumber
- 获取
#math-1 .givenNumber
的内容:(5
) - 获取
#math-1 .toAdd
的内容:(5
) - 计算总数 (
10
) 并将其附加到#math-2 .givenNumber
等等...
无计算查看
- 3 + 2 = ?
- ? + 5 = ?
- ? + 10 = ?
- ? + 7 = ?
计算后查看
- 3 + 2 = 5
- 5 + 5 = 10
- 10 + 10 = 20
- 20 + 7 = 27
谢谢!
您在转发器有机会标记它们之前查询转发器的项目,这导致 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>
由于dom-repeat绑定需要时间,所以调用后直接设置参数会有时间差,建议稍等再调用就可以了
英文不好,希望你看懂,谢谢