Polymer get changes from template dom-repeat - polymer

In order to get the changes from the input I use the following
<template is="dom-repeat" items="{{employees}}">
<div>First name: <input on-change="cambiado" value="{{item.first::change}}"></div>
<div>Last name: <input on-change="cambiado" value="{{item.last::change}}"></div>
</template>
...
<script>
...
cambiado(e){
var datos=this.employees[e.model.__data.index]
setTimeout(function() {
console.log(datos.first+' '+datos.last)
}, 1000);
}
...
</script>
but I am sure that Polymer can get the event in an easer way or just get the input changed. Thanks.
This the full element with the observers that does not work:
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id='employee-list'>
<template>
<div>Employee List</div>
<p></p>
<template is="dom-repeat" items="{{employees}}">
<div>First name: <input value="{{item.first}}"></div>
<div>Last name: <input value="{{item.last}}"></div>
</template>
</template>
<script>
class EmployeeList extends Polymer.Element {
static get is() { return 'employee-list' }
static get properties() {
return {
item: {
type: Object,
value: function () {
return {};
}
}
}
}
static get observers() {
return [
'itemChanged(item.*)'
]
}
constructor() {
super()
this.employees = [
{ first: 'Bob', last: 'Li' },
{ first: 'Ayesha', last: 'Johnson' },
{ first: 'Fatma', last: 'Kumari' },
{ first: 'Tony', last: 'Morelli' }
];
}
itemChanged(first) {
if (first) {
console.log('new first: ' + first);
} else {
console.log('first is undefined');
}
}
}
customElements.define(EmployeeList.is, EmployeeList)
</script>
</dom-module>

You can use observer, so when some property of the itemobject get changed named function is called:
observers: [
'itemChanged(item.*, cambiado)'
]
Docs: https://www.polymer-project.org/1.0/docs/devguide/observers

Related

how to bind the values using object in polymer 3.x?

I'm trying to bind the values using an object reference like this:
this.set('state', tab1Data);
but values are not binding with respective input fields.
We are using the polymer 3.x version
It depends very much on where you bind your data and how you bind it.
As you provide not so much information on the concrete context, I would guess, that you bind your data, outside the element ths calls this.set('state', ...) .
Then your property needs to have the notify-flag been set to true, otherwise changes won't be propagated outside.
The following code shows this behavior:
<html>
<head>
<script src="https://unpkg.com/#webcomponents/webcomponentsjs#latest/webcomponents-loader.js"></script>
</head>
<body>
<script type="module">
import {PolymerElement, html} from 'https://unpkg.com/#polymer/polymer/polymer-element.js?module';
import 'https://unpkg.com/#polymer/paper-button/paper-button.js?module';
class MyElement extends PolymerElement {
static get properties() {
return {
someData: {
type: Object,
value: () => {return {}},
notify: true
},
otherData: {
type: Object,
value: () => {return {}},
notify: false
},
counter: Number
}
}
constructor() {
super();
this.counter = 0;
}
static get template() {
return html`
<style> :host { display: block; } .mood { color: green; } </style>
Mood: <span class="mood">[[someData.mood]] ([[otherData.mood]])</span>
<paper-button raised on-click="setNewObject">set object</paper-button>
<paper-button raised on-click="setNewValue">set value</paper-button>
`;
}
setNewObject() {
this.counter++
const mood = `good [${this.counter}]`
this.set('someData', {mood: mood});
this.set('otherData', {mood: mood});
}
setNewValue() {
this.counter++
const mood = `better [${this.counter}]`
this.set('someData.mood', mood);
this.set('otherData.mood', mood);
}
}
customElements.define('my-element', MyElement);
class MySecondElement extends PolymerElement {
static get properties() {
return {
mood: String
}
}
static get template() {
return html`Web Components are <span>[[mood]]</span>!`;
}
}
customElements.define('my-second-element', MySecondElement);
class MyApp extends PolymerElement {
static get template() {
return html`
<my-element some-data="{{someData}}" other-data="{{otherData}}" ></my-element>
<h2>notify true</h2>
<my-second-element mood="[[someData.mood]]"></my-second-element>
<h2>notify false</h2>
<my-second-element mood="[[otherData.mood]]"></my-second-element>
`;
}
}
customElements.define('my-app', MyApp);
</script>
<my-app></my-app>
</body>
</html>
You should put the code on the value which set on the localstorage. I show it here.
import '#polymer/iron-localstorage/iron-localstorage.js';
....
<iron-localstorage name="user-info" value="{{userInfo}}" on-iron-localstorage-load-empty="initializeUserInfo"></iron-localstorage>
<vaadin-text-field id="test">
........
initializeUserInfo(){
this.set('userInfo', []);
}
ready(){
super.ready();
this.set('userInfo', this.$.test.value);
}
This is able to set data in the localstorage.

Need to navigate to next element in an array in Polymer on button click

I have an array of objects that contain emp info like name age etc and I have a page with previous and next buttons. I want to be able to navigate to the object in the array after clicking on the next button. Do I need use something like redux to achieve this or is there another way to do this. Is there a way to do this in polymer directly.
<dom-module id="my-quiz">
<template>
<div>Employee List</div>
<button on-click="prev">Previous</button>
<button on-click="next">Next</button>
</template>
<script>
class Quiz extends Polymer.Element {
static get is() { return 'my-quiz'; }
// set this element's employees property
constructor() {
super();
this.employees = [
{ name: 'Bob', id: 'b1' },
{ name: 'Ayesha', id: 'b2' },
{ name: 'Fatma', id: 'b3' },
{ name: 'Tony', id: 'b5' }
];
}
prev() {
console.log("prev");
}
next() {
console.log("next");
}
}
window.customElements.define(Quiz.is, Quiz);
</script>
</dom-module>
Here an example how to do this. There may other ways too. :
<div>Employee ID: [[_calculateId(index)]] Name: [[_calculateName(index)]]</div>
<button on-click="prev">Previous</button>
<button on-click="next">Next</button>on>
</template>
<script>
class MyTest extends Polymer.Element {
static get is() { return 'my-test'; }
static get properties() { return {
index:{
type:Number,
value:0
}
}}
// set this element's employees property
constructor() {
super();
this.employees = [
{ name: 'Bob', id: 'b1' },
{ name: 'Ayesha', id: 'b2' },
{ name: 'Fatma', id: 'b3' },
{ name: 'Tony', id: 'b5' }
];
}
_calculateName(i) { return this.employees[i].name }
_calculateId (i) { return this.employees[i].id }
prev() {
console.log("prev");
if (this.index>0) { this.index -= 1 }
}
next() {
console.log("next");
if (this.index < this.employees.length-1){this.index +=1}
}
}
customElements.define(MyTest.is, MyTest);
Demo

How to access a JSON value with Vue.js without using v-for

I have the following json:
[{id: 3,
pais: "Chile",
fuso_atual: "-3",
fuso_api: "-7200",
dst: "1",
dst_start: "1476586800",
dst_end: "1487469599",
created_at: null,
updated_at: "2016-12-11 19:19:11"
}]
and I want to access this properties, but without using v-for or something like this, I want a simple access (in my html) like {{paises[0].pais}}, but when I try this, I get an error "Cannot read property 'pais' of undefined(…)"
My component:
var getTimeZone = {
template: '#time-zone-list-template',
data: function(){
return {
paises: []
}
},
created: function(){
this.getTimeZone2();
},
methods: {
getTimeZone2: function(){
this.$http.get('api/paises').then((response) => {
this.paises = response.body;
});
}
}
};
var app = new Vue({
el: '#app',
components: {
'time-zone-list': getTimeZone
}
});
My html:
<div id="app">
<time-zone-list></time-zone-list>
</div>
<template id="time-zone-list-template">
<div class="time-and-date-wrap">
{{ paises[0].pais }}
</div>
</template>
Any idea?
edit: I can access {{ paises[0] }} with success, but not .pais
edit2: If I use v-for I can navigate in the inside properties
Thanks
I found another solution =>>> v-if="paises.length" this solved my problem =]
var getTimeZone = {
template: '#time-zone-list-template',
data: function(){
return {
paises: []
}
},
created: function(){
this.getTimeZone();
},
methods: {
getTimeZone: function(){
this.$http.get('api/paises').then((response) => {
this.paises = response.body;
});
}
}
};
Then in my template
<template id="time-zone-list-template">
<div class="time-and-date-wrap" v-if="paises.length">
{{ paises[0].pais }}
</div>
</template>
Jeff Mercado's answer in the comment correctly describes why this fails.
You could add a computed property like this...
var getTimeZone = {
template: '#time-zone-list-template',
data: function(){
return {
paises: []
}
},
created: function(){
this.getTimeZone2();
},
computed: {
elPrimerPais: function() {
return this.paises.length > 0 ? this.paises[0].pais : '';
}
},
methods: {
getTimeZone2: function(){
this.$http.get('api/paises').then((response) => {
this.paises = response.body;
});
}
}
};
Then in your template you can do this..
<template id="time-zone-list-template">
<div class="time-and-date-wrap">
{{ elPrimerPais }}
</div>
</template>

How to reflect change from child to parent in Polymer

The current code is below. I have element-value in the main file. This value is passed to the child elements app-element and from there to app-element-add.
The value changes in app-element-add. But I cannot get the value reflected in the main element.
The observers never get invoked.
main.html
<app-element element-value = {{ elementValue }}></app-element>
Polymer({
is: 'app-main-element',
properties: {
elementValue: {
type:Array,
notify:true,
observer:'listUpdated'
}
});
app-element.html
<app-element-add element-value = {{ elementValue }}></app-element-add>
Polymer({
is: 'app-element',
properties: {
elementValue: {
type:Array,
notify:true,
observer:'listUpdated'
}
});
app-element-add.html
Polymer({
is: 'app-element-add',
properties: {
elementValue: {
type:Array,
notify:true,
reflectToAttribute:true
}
});
Any hints on how to reflect changes in app-element-add in app-main-element. Thanks.
You don't need to use reflectToAttribute here. The only option required here is notify. However, your current code works:
HTMLImports.whenReady(_ => {
"use strict";
Polymer({
is: 'app-main-element',
properties : {
elementValue: {
type: Array,
notify: true,
observer: 'listUpdated',
value: _ => [100,200,300]
}
},
listUpdated: function() {
console.log('[app-main-element] list updated');
},
ready: function() {
console.log('[app-main-element] ready');
}
});
Polymer({
is: 'app-element',
properties : {
elementValue: {
type: Array,
notify: true,
observer: 'listUpdated'
}
},
listUpdated: function() {
console.log('[app-element] list updated');
},
ready: function() {
console.log('[app-element] ready');
}
});
Polymer({
is: 'app-element-add',
properties : {
elementValue: {
type: Array,
notify: true
}
},
ready: function() {
console.log('[app-element-add] ready (will set elementValue in 1000ms)');
this.async(_ => {
console.log('[app-element-add] updating elementValue');
this.elementValue = [1,2,3];
}, 1000);
}
});
});
<head>
<base href="https://polygit.org/polymer+1.11.0/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<app-main-element></app-main-element>
<dom-module id="app-main-element">
<template>
<app-element element-value={{elementValue}}></app-element>
<div>app-main-element.elementValue = [[elementValue]]</div>
</template>
</dom-module>
<dom-module id="app-element">
<template>
<app-element-add element-value={{elementValue}}></app-element-add>
<div>app-element.elementValue = [[elementValue]]</div>
</template>
</dom-module>
<dom-module id="app-element-add">
<template>
<div>app-element-add.elementValue = [[elementValue]]</div>
</template>
</dom-module>
</body>
codepen

using paper-datatable-card in a custom-tag

//index.html
<html>
<head>
<link rel="import" href="test-table.html">
</head>
<body>
<template is="dom-bind" id="index">
<test-table data="{{data}}" ></test-table>
</template>
</body>
</html>
Polymer({
is: "test-table",
properties : {
data : {type : Array},
}
/*I dont know where should I put this stuff
"queryForIds:"
"getByIds :"
"set:"
"length:0"
*/
});
<dom-module id="test-table">
<template>
<paper-datatable-card id="datatableCard" header="Users" page-size="10" data-source="{{data}}" id-property="_id" selected-ids="{{selectedIds}}">
<paper-datatable id="datatable" data='{{data}}' selectable multi-selection selected-items="{{selectedItems}}">
<paper-datatable-column header="Id" property="_id" sortable>
<template>
<span>{{value}}</span>
</template>
</paper-datatable-column>
</paper-datatable>
</paper-datatable-card>
</template>
</dom-module>
as part of single page application I am using “paper-datatable-card” in my own custom-tag. I able to display the records but I’m not getting where I have to put the code for pagination. And I don’t want to put all records into dataSource at a time.
Any help is appreciated,
Thank you,
Venkat.
From within your Polymer component, you can set data in the ready method:
ready: function() {
this.data = {
queryForIds: function(sort, page, pageSize){
// implement me
},
getByIds: function(ids){
// implement me
},
set: function(item, property, value){
// implement me
},
length:0
};
}
Your comment question:
So I am unable to put the code from lines 117 to 133 in my custom elements as it doesnt support dom-bind
Answer (in Polymer 2.0) you can do it in your component constructor all the methods and all the data variables:
class YourComponent extends Polymer.Element {
contructor() {
super();
//in case if you use paper-datatable-card
this.data = {
get: function (sort, page, pageSize) {
return new Promise((resolve, reject) => {
const exampleData = [
{ 'name': 'someName1' },
{ 'name': 'someName2' }
];
resolve(exampleData);
});
},
set: function(item, property, value){...},
length: 1
};
//in case if you use paper-datatable only then without get or set properties
this.data = [ { name: 'someName' } ];
}
}