Polymer iron-list dynamically adding items? - polymer

I'm trying to migrate some code from Polymer 0.5 to 1.x, this means moving from core-list to iron-list. However, I can not figure out an iron equivalent to how I was adding items to the core-list.
<core-list height="85">
<template>
<div class="{{ {selected: selected} | tokenList }}" style="padding:5px;"><paper-fab mini icon="arrow-forward" title="arrow-forward"></paper-fab> <!--{{index}}-->{{model.name}}</div>
</template>
</core-list>
which is called updated via...
document.querySelector('core-list').data = $.parseJSON('[{"name":"One"},{"name":"Two"}]');
Anyone have any suggestions?
Update : Jul-23-2015 12:20PM PST
#Zikes
Following the suggestion posted, I have the following.
<dom-module id="my-element">
<template>
<iron-list items="[[myItems]]" as="item">
<template>
<div>[[item.name]]</div>
</template>
</iron-list>
</template>
<script>
Polymer({
is:'my-element',
properties: {
myItems: Array
},
addItem: function(item) {
this.push('myItems', {name: item});
}
});
</script>
</dom-module>
If this is setup right, how would I go about calling the addItem method from elsewhere?
Update : Jul-23-2015 1:58PM PST
#Zikes
Following is my current code. While I can manipulate the array, values added to it in the ready or addItem method are not being displayed.
<dom-module id="fnord-element">
<template>
<iron-list items="[[myItems]]" as="item">
<template>
<div class="item">[[item.name]]</div>
</template>
</iron-list>
</template>
<script>
Polymer({
is:'fnord-element',
properties: {
myItems: {
type: Array,
notify: true
}
},
addItem: function(item) {
//this.push("myItems", {"name":item});
this.myItems=[{name:item}];
alert(this.myItems[0].name);
//alert(item);
},
ready: function() {
//alert('fnord');
this.myItems=[{name:"One"},{name:"Two"}];
}
});
</script>
</dom-module>
<fnord-element id="fnord"></fnord-element>
<paper-button raised onclick="document.querySelector('#fnord').addItem('John Doe');">Test</paper-button>

iron-list uses the items property to generate its items, similar to dom-repeat. What you can do is simply bind it to an Array in your component, like so:
<dom-module id="my-element>
<template>
<iron-list items="[[myItems]]">
<template>
<div>[[item]]</div>
</template>
</iron-list>
</template>
<script>
Polymer({
is:'my-element',
properties: {
myItems: Array
}
});
</script>
</dom-module>
Then, just follow the rules for modifying an Array property and you're all set!

Related

Polymer dom-if: how do I implement a negative condition?

I have a Polymer element that uses <template is="dom-if"... to provide different HTML content depending on a condition.
Polymer dom-if has no else condition, so needs a negative if condition to simulate it.
Something like this:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<dom-module id="test-thing">
<template>
<template is="dom-if" if="{{title}}" restamp>
<b>[[title]]</b>
</template>
<template is="dom-if" if="{{!title}}" restamp>
<i>no title</i>
</template>
</template>
<script>
Polymer({
is: 'test-thing',
properties: {
title: String
}
});
</script>
</dom-module>
<div>
With negative condition:
<test-thing></test-thing>
</div>
<div>
With positive condition:
<test-thing title="Has Title"></test-thing>
</div>
Only that doesn't work - the negative condition never passes.
How should this be implemented?
You must use a default empty value for your title property:
title:{type: String,value:''}
Like so:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<dom-module id="test-thing">
<template>
<template is="dom-if" if="{{title}}" restamp>
<b>[[title]]</b>
</template>
<template is="dom-if" if="{{!title}}" restamp>
<i>no title</i>
</template>
</template>
<script>
Polymer({
is: 'test-thing',
properties: {
title: {type: String,value:''}
}
});
</script>
</dom-module>
<div>
With negative condition:
<test-thing></test-thing>
</div>
<div>
With positive condition:
<test-thing title="Has Title"></test-thing>
</div>

Computed Binding with Polymer

This is an excerpt of my codes:
<template is="dom-bind">
<iron-ajax auto
url="####"
params=""
handle-as="json"
last-response="{{ajaxResponse}}"></iron-ajax>
<template is="dom-repeat" items="[[ajaxResponse.Items]]">
<div>
[[_formatDate(item.ID.N)]]
</div>
</template>
</template>
...
<script>
Polymer({
is: 'home-view',
_formatDate: function(ID) {
console.log("TEST");
return "TEST";
}
});
</script>
I am getting this Console Warning:
[Warning] [dom-bind::_annotatedComputationEffect]: – "compute method `_formatDate` not defined" (data:text/javascript;charset=utf-8,(fu…%0A, line 265, x10)
So it seems that I do not know how to define _formatDate correctly so that it is recognized by Polymer. Can someone please help?
It looks like you're correctly declaring and using _formatDate().
The warning comes from dom-bind, which is intended only for bindings in index.html, not inside dom-module. You should remove the is="dom-bind" from your top template.
<head>
<base href="https://polygit.org/polymer+1.6.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<home-view></home-view>
<dom-module id="home-view">
<template>
<template is="dom-repeat" items="[[items]]">
<div>[[_formatDate(item)]]</div>
</template>
</template>
<script>
// For cross-browser compatibility, HTMLImports.whenReady()
// needed in index.html only
HTMLImports.whenReady(function() {
Polymer({
is: 'home-view',
properties: {
items: {
type: Array,
value: function() { return ['hello', 'world']; }
}
},
_formatDate: function(id) {
console.log('id', id);
return id;
}
});
});
</script>
</dom-module>
</body>

Polymer: Passing properties to child element doesn't work

I'm trying to output data from a custom Polymer component <data-component> in an <iron-list> but nothing is shown when I open the page. It works when I pass an array of objects directly to the iron-list like <iron-list items='[{"name": "test1"}, {"name":"test2"}]' >
What am I doing wrong here and is the <template is="dom-bind" id="t"> mandatory?
index.html
<html>
<head>
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../data-component.html">
<link rel="import" href="../../iron-list/iron-list.html">
</head>
<body unresolved>
<template is="dom-bind" id="t">
<data-component>
<!--<iron-list items='[{"name": "test1"}, {"name":"test2"}]' > WORKS -->
<iron-list items="{{data}}" >
<template>
<div>
Name: <span>{{item.name}}</span>
</div>
</template>
</iron-list>
</data-component>
</template>
</body>
</html>
data-component.html
<link rel="import" href="../polymer/polymer.html">
<dom-module id="data-component">
<template>
<content></content>
</template>
</dom-module>
<script>
window.coolData = [
{"name": "Bob"},
{"name": "Tim"},
{"name": "Mike"}
];
Polymer({
is: 'data-component',
properties: {
data: {
value: window.coolData
}
}
});
</script>
I'm going to suggest an alternative answer to what I have already posted. If you want your data-component to always contain the iron-list then you can use this version here. However, if the content of the data-component should be more flexible use my other answer.
If you move the iron-list inside the data-component you can remove the dom-bind in your index.html.
data-component.html
<link rel="import" href="../polymer/polymer.html">
<dom-module id="data-component">
<template>
<iron-list items="{{data}}" >
<template>
<div>
Name: <span>{{item.name}}</span>
</div>
</template>
</iron-list>
</template>
</dom-module>
<script>
window.coolData = [
{"name": "Bob"},
{"name": "Tim"},
{"name": "Mike"}
];
Polymer({
is: 'data-component',
properties: {
data: {
type: Array,
value: window.coolData
}
}
});
</script>
index.html
<body unresolved>
<data-component></data-component>
</body>
You also have to add a data-binding to your data-component. Otherwise, the system does not know that data (in your iron-list) should refer to the data property in your custom element.
<data-component data="{{data}}">
<iron-list items="{{data}}" >
...
</iron-list>
</data-component>
The dom-bind is necessary if you want to have data-binding outside of a Polymer element, which seems to be the case here.
You should also make sure that the data property is configured to notify changes and that its type is set to Array.
Polymer({
is: 'data-component',
properties: {
data: {
type: Array,
value: window.coolData,
notify: true
}
}
});

Computed property with firebase element in polymer 1.0

I have an element where I receive some data from firebase which looks like that:
<dom-module id="my-positions-list">
<template is="dom-bind">
<firebase-collection data="{{aa}}"
location="https://myapp.firebaseio.com/positions">
</firebase-collection>
<template is="dom-repeat" items="[[aa]]" as="item">
<p><span>{{url}}</span></p>
</template>
</template>
<script>
(function () {
Polymer({
is: 'my-positions-list',
properties: {
url:{
type:String,
computed: 'url(this.item.title)'
}
},
url: function(title) {
return "/positions/" + title;
}
});
})();
</script>
</dom-module>
I am trying to create a computed property "url" using the title attribute of the "item" but had no luck, any idea how to achieve that?
I also get this weird message in my console from the polymer-mini.html file:
[my-positions-list::_prepTemplate]: top-level Polymer template must not be a type-extension, found template Move inside simple .
Any idea how to fix it?
Try this:
<dom-module id="my-positions-list">
<template is="dom-bind">
<firebase-collection data="{{aa}}"
location="https://myapp.firebaseio.com/positions/"></firebase-collection>
<template is="dom-repeat" items="[[aa]]">
<p><span>{{url(item.title)}}</span></p>
</template>
</template>
</dom-module>
<script>
(function () {
Polymer({
is: 'my-positions-list',
url: function(title) {
return "/positions/" + title;
}
});
})();
</script>
here the it in jsbin http://jsbin.com/lokegu/edit?html,output

How to global firebase polymer data binding?

I want to use <firebase-login> user object to check if user logged in for my elements. How do I global the user object without calling below code in every custom element?
<firebase-login id="login"
user="{{user}}"
statusKnown="{{statusKnown}}"
location="FIREBASE_URL"
provider="{{provider}}"
on-error="{{error}}"></firebase-login>
Create a custum-element that looks something like this,
<polymer-element name="example" attributes="user">
<template>
<firebase-login
id="login"
user="{{user}}"
statusKnown="{{statusKnown}}"
location="FIREBASE_URL"
provider="{{provider}}"
on-error="{{error}}">
</firebase-login>
</template>
<script>
Polymer({
})
</script>
</polymer-element>
Then use pvc-globals or create another custom element that passes globals Polymer has an example app-globals where they show how to do this.
<polymer-element name="app-example" attributes="globals">
<template>
<pvc-globals value="{{globals}}"></pvc-globals>
<example-element user="{{user}}"></example-element>
</template>
<script>
Polymer({
ready: function () {
this.globals.user = this.user;
}
});
</script>
</polymer-element>
Or from within the example element:
<polymer-element name="example" attributes="user globals">
<template>
<pvc-globals value="{{globals}}"></pvc-globals>
<firebase-login
id="login"
user="{{user}}"
statusKnown="{{statusKnown}}"
location="FIREBASE_URL"
provider="{{provider}}"
on-error="{{error}}">
</firebase-login>
</template>
<script>
Polymer({
ready: function () {
this.globals.user = this.user;
}
})
</script>
</polymer-element>
Hope this helps!