Polymer feed value into second dom-repeat - polymer

I'm trying to use a dom-repeat inside a dom-repeat over a json array inside a json array. How can pass a value from the first array over to the second dom-repeat?
To illustrate, I have the following json array which loads fine:
"books": [
{
"title": "book1",
"slug": "b1",
"authors": ["author1","author2"],
"blurb": "Some text"
},
{
"title": "book2",
"slug": "b2",
"authors": ["author2","author3"],
"blurb": "some more text"
}]
I'm iterating over the array 'books' and retrieve title and blurb. Then underneath, I want both authors of each book listed and I also want a link to each one in the format of /slug/author (f.i. /b1/author1). But because in the second dom-repeat I redefine "items", the 'slug' is no longer available. How do I go about this?
<template>
<iron-ajax
auto
url="somelist.json"
handle-as="json"
last-response="{{someList}}"></iron-ajax>
<template is="dom-repeat" items="{{someList.books}}">
<paper-collapse-group>
<paper-collapse-item header$="{{item.title}}">
<p>{{item.blurb}}</p>
</paper-collapse-item>
<template is="dom-repeat" items="{{item.authors}}">
<a href$="/[[slug]]/[[item]]">{{item}}</a></div>
</template>
</paper-collapse-group>
</template>
</template>
I'm also very new to Polymer so thank you for helping me learn!

Use the as attribute to use a custom name for the item property.
Example:
<template>
<iron-ajax
auto
url="somelist.json"
handle-as="json"
last-response="{{someList}}"></iron-ajax>
<template is="dom-repeat" items="{{someList.books}}" as="book">
<paper-collapse-group>
<paper-collapse-item header$="{{book.title}}">
<p>{{book.blurb}}</p>
</paper-collapse-item>
<template is="dom-repeat" items="{{book.authors}}" as="author">
<a href$="/[[book.slug]]/[[author]]">{{author}}</a></div>
</template>
</paper-collapse-group>
</template>
</template>

So what you can do is to create another element, let's say that would look like:
<dom-module id="authors">
<template>
<template is="dom-repeat" items="[[authors]]">
<a href$="/[[slug]]/[[item]]">[[item]]</a>
</template>
</template>
<script>
Polymer({
is: 'authors',
properties: {
authors: Array,
slug: String
},
});
</script>
</dom-module>
and then inject it into your code like:
<template is="dom-repeat" items="[[someList.books]]">
<paper-collapse-group>
<paper-collapse-item header$="[[item.title]]">
<p>[[item.blurb]]</p>
</paper-collapse-item>
<authors slug="[[item.slug]]" authors="[[item.authors]]"></authors>
</paper-collapse-group>
</template>

Related

Using <template is="dom-if" with a condition

I have a <template is="dom-if" if=... that I want to use with a logical condition.
Any binding I try appears to be truthy:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<dom-module id="test-thing">
<template>
<template is="dom-if" if="{{title == 'foo'}}" restamp>
Title is <b>FOO</b>
</template>
<template is="dom-if" if="{{title}} == 'bar'" restamp>
Title is <b>BAR</b>
</template>
Actual: "{{title}}"
</template>
<script>
Polymer({
is: 'test-thing',
properties: {
title: {type: String,value:''}
}
});
</script>
</dom-module>
<div>
Title: foo<br>
<test-thing title="foo"></test-thing>
</div>
<div>
Title: bar<br>
<test-thing title="bar"></test-thing>
</div>
<div>
Title: abc<br>
<test-thing title="abc"></test-thing>
</div>
What is the correct way to apply an if condition to a dom-if template?
you have to define your function.
<template is="dom-if" if="[[_isEqualTo(title, 'Foo')]]">
and then in script:
function _isEqualTo(title, string) {
return title == string;
}
whenever is property title changed, function _isEqualTo is called. so you don't have to take care of observing property or something.
function _isEqualTo is called with 2 parameters, the second one is just plain string you want to compare some value with.
The only logic you can use in a binding is not.
for instance:
<template is="dom-if" if="{{_isEqualTo(title, 'Foo')}}">
<template is="dom-if" if="{{!_isEqualTo(title, 'Foo')}}">
If your data was such that Foo was boolean or had an attribute that "Foo":true or "isFoo":true . Then you could just do:
<template is="dom-if" if="{{isFoo}}">
Foo
</template>

How to rerender the complete dom-repeat in Polymer on a Array change

I just started playing with Polymer and have been struggling to solve following issue.
In below code when the button is clicked myItem array is changed and parent template dom-repeat is rerendered, but the child template dom-repeat is not updated.
The reason might be the child dom-repeat is bound to the function _get.
<dom-module id="my-element">
<template>
<button on-click="_removeLastTwo">switch</button>
<template is="dom-repeat" items="{{myItem}}">
<ul>
<template is="dom-repeat" items="{{_get(item)}}">
<li>{{item}}</li>
</template>
</ul>
</template>
</template>
</dom-module>
<script>
Polymer({
is: 'my-element',
properties: {
data: {
type: Array,
value: [9,8]
},
myItem:{
type:Array,
value:[1,2,3,4,5]
}
},
_get:function(t){
var d = this.myItem.length;
return [d+1,d+2]
},
_removeLastTwo: function(){
this.myItem = [1,2]
}
});
</script>
How can I overcome this issue, check it at http://jsbin.com/misuvehuwe/edit?html,output . Am I missing any basic approach??

Polymer 1.0 dom-repeat does not trigger filter

Have a simple paper-card with an iron-ajax which is being iterated ok but the filter I have made never triggers. The JSON being fetched via the iron-ajax has an integer value for the day of the week and I only want to have the ones with value of 0.
Tried the filter field with following values:
filter="{{isMonday}}"
filter="{{isMonday(item)}}"
filter="isMonday"
filter="isMonday(item)"
All of these with and without the observe
Component code:
<dom-module id="se-ligor">
<template>
<template is="dom-bind">
<iron-ajax auto
url="http://localhost:5000/leagues/1"
handle-as="json"
last-response="{{ajaxResponse}}">
</iron-ajax>
<template name="my-paper" is="dom-repeat" items="[[ajaxResponse]]" filter="{{isMonday}}" observe="dayofweek">
<paper-card heading="[[item.name]]">
<div class="card-content">
[[item.description]]
[[item.dayofweek]]
</div>
<div class="card-actions">
<paper-button>Some action</paper-button>
</div>
</paper-card>
</template>
</template>
</template>
<script>
Polymer({
is: "se-ligor",
isMonday: function (item) {
console.log(item.dayofweek);
if (item.dayofweek == 0)
return True;
}
});
</script>
</dom-module>
The dom-bind template is intended for binding only in index.html, not in dom-module, so that template should be removed.
The filter property takes the name of a method without delimiters (i.e., no brackets) on your Polymer constructor object.
<!-- in <dom-module> -->
<template is="dom-repeat" items="[[x]]" filter="isMonday" observe="dayofweek">...</template>
<script>
Polymer({
isMonday: function(item) {...}
});
</script>
isMonday contains a typo in return True. In JavaScript, the keyword is lowercase: true.
plunker demo

polymer 1.3 dom-repeat two arrays

I need a dom-repeat to loop over one array and for each item I also need an element of a second array in the same index location.
<template is="dom-repeat" items="[[my_array1]]">
<div>[[item]]</div>
<div>[[my_array2[index]]] </div> <!-- this does not work -->
</template>
How to solve?
You'll need to use a computed binding:
<template is="dom-repeat" items="[[my_array1]]">
<div>[[item]]</div>
<div>[[getElementFromArray(index, my_array2)]]</div>
</template>
<script>
Polymer({
is: 'my-element',
getElementFromArray: function(index, arr) {
return arr[index];
}
})
</script>

polymer submenus and items from json

I'm trying to generate Polymer submenus and items from json. The code is just nested submenu & item templates:
<polymer-element name="years-submenu" noscript>
<template>
<core-ajax auto url="../json/years and offices.json" response="{{items}}" handleAs="json"></core-ajax>
<template repeat="{{item in items}}">
<core-submenu icon="visibility" label="{{item.year}}">
<template repeat="{{office in item.offices}}">
<core-item id="{{item.year}} {{office}}" label="{{item.year}} {{office}}"></core-item>
</template>
</core-submenu>
</template>
</template>
</polymer-element>
The json data could be structured any old way, but currently it looks like this:
[
{
"offices": [
"Mayor",
"Council At-Large"
],
"year": "2014"
},
{
"offices": [
"Council Chairman",
"Council At-Large",
"Council Ward 2",
"Council Ward 4"
],
"year": "2012"
}
]
This renders the years, but not the office names. Oddly, if I inspect the elements in chrome, I can see that it is inserting the {{item.year}} and {{office}} for the id but not for the label. I've tried various ways of explicitly binding, but to no avail; of course, I may have been trying the wrong ways. Any ideas on how to make this work would be very much appreciated.
It turns out that if I put wrap my submenu code inside within my custom element (rather than calling the submenu from the main page that wraps my custom element inside , it works.
So, calling the element posted in the question as follows does not work:
<core-menu selected="{{selected}}" valueattr="id" theme="core-light-theme">
<years-submenu></years-submenu>
</core-menu>
But the following called from the main page does work:
<polymer-element name="years-menu" noscript>
<template>
<core-menu selected="{{selected}}" valueattr="id" theme="core-light-theme">
<core-ajax auto url="../json/years and offices.json" response="{{items}}" handleAs="json"></core-ajax>
<template repeat="{{item in items}}">
<core-submenu icon="visibility" label="{{item.year}}">
<template repeat="{{office in item.offices}}">
<core-item id="{{item.year}} {{office}}" label="{{item.year}} {{office}}"></core-item>
</template>
</core-submenu>
</template>
</core-menu>
</template>
</polymer-element>
I don't fully understand why, but problem solved.
I created a polymer element to create a menu from JSON. It has some other cool features, and I am going to continue to enhance it.
It doesnt exactly fit your question but check it out.
Create a github issue/pull request if you have any issues/ideas
https://github.com/sup3rb0wlz/nb-menu