computed binding on dom-repeat items property - polymer

I'm building a relatively simple page in which are dynamically created a series of paper-tabs and core-pages. The idea is the user -through a paper-input- indicates the number of paper-tabs and core-pages that want and these are added automatically using dom-repeat's. The first part of this functionality is already implemented, but I have a problem with the second.
Inside of the paper-pages I need 3 paper-inputs and buttons, so the user can create/delete new inputs. My idea is implement a function that will create many arrays as the user indicatedand fill them with the inputs.
I have implemented a computed-binding to scroll through each of the Array's, but is not working. The X iron-pages are created without problems but no inputs are added.
Below is the code:
<!DOCTYPE html>
<html>
<head>
<!-- Dependencias/Elementos -->
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-label/iron-label.html">
<link rel="import" href="../../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-tabs/paper-tabs.html">
</head>
<dom-module id="protocolo-app">
<style>
:host {
display: block;
}
.card {
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
padding: 16px;
margin: 24px;
border-radius: 5px;
background-color: #fff;
color: #757575;
}
.inputGray{
background-color: #555;
color: #fff;
}
h1 {
font-size: 22px;
margin: 16px 0;
color: #212121;
}
paper-tabs[grayTab]{
background: #eee;
margin-top: 3%;
margin-bottom: 3%;
}
.flex {
#apply(--layout-horizontal);
}
.flex-horizontal-with-ratios {
#apply(--layout-horizontal);
}
.flexchild {
#apply(--layout-flex);
}
.flex2child {
#apply(--layout-flex-2);
}
.flex3child {
#apply(--layout-flex-3);
}
.flex-center-justified {
#apply(--layout-horizontal);
#apply(--layout-center-justified);
}
.flex-equal-justified {
#apply(--layout-horizontal);
#apply(--layout-justified);
}
.flex-equal-around-justified {
#apply(--layout-horizontal);
#apply(--layout-around-justified);
}
paper-button.gray {
background: #eee;
color: #000;
}
paper-button.gray:hover {
background: #555;
}
paper-button[disabled],
paper-button[toggles][active] {
background: red;
}
</style>
<template>
<div class="card">
<h1>Alta de Protocolos</h1>
<div class="cointainer flex-horizontal-with-ratios">
<div class="flex2child">
<iron-label>Nombre de Protocolo</iron-label>
</div>
<div class="flexchild">
<iron-label>Núm. Visitas</iron-label>
</div>
</div>
<div class="cointainer flex-horizontal-with-ratios">
<div class="flex2child">
<paper-input name="protocol" id="protocol" value="{{protocol}}"></paper-input>
</div>
<div class="flexchild">
<paper-input name="visit" id="visit" value="{{visits}}" prevent-invalid-input allowed-pattern="[0-9]" on-change="visitChanged"></paper-input>
</div>
</div>
<!-- Tab's Element-->
<paper-tabs selected="{{selected}}" scrollable no-slide noink grayTab>
<template id="tabs" is="dom-repeat" items="{{tabArray}}">
<paper-tab>{{item.value}}</paper-tab>
</template>
</paper-tabs>
<!-- /Tab's Element-->
<!-- iron-pages Element's-->
<iron-pages selected="{{selected}}">
<template id="pages" is="dom-repeat" items="{{tabArray}}">
<div>
<template id="inputs" is="dom-repeat" items="{{concat(tabArray.array, index)}}">
<div class="container flex">
<div>
<paper-input id="input" value= "{{item.value}}" placeholder="{{item.placeholder}}"></paper-input>
</div>
<div>
<paper-button class="gray" raised on-tap="delInput">Eliminar</paper-button>
</div>
</div>
</template>
<div class="container flex">
<paper-button class="gray" raised on-tap="addInput">Agregar</paper-button>
</div>
</div>
</template>
</iron-pages>
<!-- /iron-pages Element's-->
<div class="container flex-center-justified">
<div>
<paper-button class="gray" raised>Cancelar</paper-button>
<paper-button class="gray" raised>Guardar</paper-button>
</div>
</div>
</div>
</template>
</don-module>
<script>
Polymer({
is: 'protocolo-app',
properties: {
protocol: {
type: String,
value: ""
},
visits:{
type:Number,
value: 3,
notify: true
},
tabArray: {
type: Array,
value: [{value:"visita1"},{value:"visita2"},{value:"visita3"}]
},
inputArray: {
type: Array,
value: [{value:"",placeholder:"t1_input1"},{value:"",placeholder:"t1_input2"},{value:"",placeholder:"t1_input3"}]
}
},
//funcion que agrega input's
addInput: function(){
this.push('inputArray0',{value:"",placeholder:""});
},
//funcion que elimina input's
delInput: function(e){
this.splice('inputArray0',e.model.index,1);
},
creaArrayTabs: function(e){
console.log(this.value);
},
concat: function(v1, v2){
var res = v1 + v2;
alert("Concatenacion: " + res);
return v1 + v2;
},
//funcion que carga los arrays necesarios para la aplicacion
visitChanged: function(e){
//alert("Valor: " + this.$.visit.value);
//limpiamos el array para agregar las nuevas tabs
this.splice('tabArray',e.model);
//asignamos a la variable max el valor del input
var max = this.$.visit.value;
for (i = 0; i < max; i++) {
//alert("Prueba " + i);
this.push('tabArray',{value:"Visita " + i, array:"inputArray"});
this['inputArray'+ i] = [];
for (j = 0; j < 3; j++) {
this.push('inputArray' + i,{value:"",placeholder:"t"+ i + "_input"+j});
}
}
}
});
</script>

The main problem is this line:
<template id="inputs" is="dom-repeat" items="{{concat(tabArray.array, index)}}">
It's not clear what you're attempting to do with concat(tabArray.array, index). There is no array property on tabArray, but even if there were, concat() simply concatenates its arguments, and presumably would return a string, which is invalid input for the template repeater (i.e., the repeater's items must be bound to an Array). Removing that invalid template tag would resolve the issue.
Also, note that paper-tabs and iron-pages are bound to an uninitialized selected property, so no page view appears until a tab is clicked. You could resolve that by declaring a selected property with a default.
Here's a working demo:
<head>
<meta charset="utf-8">
<base href="https://polygit.org/polymer+1.5.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="iron-label/iron-label.html">
<link rel="import" href="iron-pages/iron-pages.html">
<link rel="import" href="paper-input/paper-input.html">
<link rel="import" href="paper-button/paper-button.html">
<link rel="import" href="paper-tabs/paper-tabs.html">
<link rel="import" href="paper-tabs/paper-tab.html">
</head>
<body>
<protocolo-app></protocolo-app>
<dom-module id="protocolo-app">
<style>
:host {
display: block;
}
.card {
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
padding: 16px;
margin: 24px;
border-radius: 5px;
background-color: #fff;
color: #757575;
}
.inputGray {
background-color: #555;
color: #fff;
}
h1 {
font-size: 22px;
margin: 16px 0;
color: #212121;
}
paper-tabs[grayTab] {
background: #eee;
margin-top: 3%;
margin-bottom: 3%;
}
.flex {
#apply(--layout-horizontal);
}
.flex-horizontal-with-ratios {
#apply(--layout-horizontal);
}
.flexchild {
#apply(--layout-flex);
}
.flex2child {
#apply(--layout-flex-2);
}
.flex3child {
#apply(--layout-flex-3);
}
.flex-center-justified {
#apply(--layout-horizontal);
#apply(--layout-center-justified);
}
.flex-equal-justified {
#apply(--layout-horizontal);
#apply(--layout-justified);
}
.flex-equal-around-justified {
#apply(--layout-horizontal);
#apply(--layout-around-justified);
}
paper-button.gray {
background: #eee;
color: #000;
}
paper-button.gray:hover {
background: #555;
}
paper-button[disabled],
paper-button[toggles][active] {
background: red;
}
</style>
<template>
<div class="card">
<h1>Alta de Protocolos</h1>
<div class="cointainer flex-horizontal-with-ratios">
<div class="flex2child">
<iron-label>Nombre de Protocolo</iron-label>
</div>
<div class="flexchild">
<iron-label>Núm. Visitas</iron-label>
</div>
</div>
<div class="cointainer flex-horizontal-with-ratios">
<div class="flex2child">
<paper-input name="protocol" id="protocol" value="{{protocol}}"></paper-input>
</div>
<div class="flexchild">
<paper-input name="visit" id="visit" value="{{visits}}" prevent-invalid-input
allowed-pattern="[0-9]" on-change="visitChanged"></paper-input>
</div>
</div>
<!-- Tab's Element-->
<paper-tabs selected="{{selected}}" scrollable no-slide noink grayTab>
<template id="tabs" is="dom-repeat" items="{{tabArray}}">
<paper-tab>{{item.value}}</paper-tab>
</template>
</paper-tabs>
<!-- /Tab's Element-->
<!-- iron-pages Element's-->
<iron-pages selected="{{selected}}">
<template id="pages" is="dom-repeat" items="{{tabArray}}">
<div>
<!--<template id="inputs" is="dom-repeat" items="{{concat(tabArray.array, index)}}">-->
<div class="container flex">
<div>
<paper-input id="input" value="{{item.value}}"
placeholder="{{item.placeholder}}"></paper-input>
</div>
<div>
<paper-button class="gray" raised on-tap="delInput">Eliminar</paper-button>
</div>
</div>
<!--</template>-->
<div class="container flex">
<paper-button class="gray" raised on-tap="addInput">Agregar</paper-button>
</div>
</div>
</template>
</iron-pages>
<!-- /iron-pages Element's-->
<div class="container flex-center-justified">
<div>
<paper-button class="gray" raised>Cancelar</paper-button>
<paper-button class="gray" raised>Guardar</paper-button>
</div>
</div>
</div>
</template>
<script>
Polymer({
is: 'protocolo-app',
properties: {
protocol: {
type: String,
value: ""
},
visits: {
type: Number,
value: 3,
notify: true
},
tabArray: {
type: Array,
value: [{value: "visita1"}, {value: "visita2"}, {value: "visita3"}]
},
inputArray: {
type: Array,
value: [{value: "", placeholder: "t1_input1"}, {value: "", placeholder: "t1_input2"}, {
value: "",
placeholder: "t1_input3"
}]
},
selected: {
type: Number,
value: 0
}
},
//funcion que agrega input's
addInput: function() {
this.push('inputArray0', {value: "", placeholder: ""});
},
//funcion que elimina input's
delInput: function(e) {
this.splice('inputArray0', e.model.index, 1);
},
creaArrayTabs: function(e) {
console.log(this.value);
},
concat: function(v1, v2) {
var res = v1 + v2;
alert("Concatenacion: " + res);
return v1 + v2;
},
//funcion que carga los arrays necesarios para la aplicacion
visitChanged: function(e) {
//alert("Valor: " + this.$.visit.value);
//limpiamos el array para agregar las nuevas tabs
this.splice('tabArray', e.model);
//asignamos a la variable max el valor del input
var max = this.$.visit.value;
for (i = 0; i < max; i++) {
//alert("Prueba " + i);
this.push('tabArray', {value: "Visita " + i, array: "inputArray"});
this['inputArray' + i] = [];
for (j = 0; j < 3; j++) {
this.push('inputArray' + i, {value: "", placeholder: "t" + i + "_input" + j});
}
}
}
});
</script>
</dom-module>
</body>
codepen
Note there seems to be other issues in your code, but that's beyond the scope of this question.

After several attempts, the only solution was migrate to a multidimensional array structure and modify the add and del functions to interact with the new array structure.
Below the final code:
<!DOCTYPE html>
<html>
<head>
<!-- Dependencias/Elementos -->
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-label/iron-label.html">
<link rel="import" href="../../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-tabs/paper-tabs.html">
</head>
<dom-module id="protocolo-app">
<style>
:host {
display: block;
}
.card {
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
padding: 16px;
margin: 24px;
border-radius: 5px;
background-color: #fff;
color: #757575;
}
.inputGray{
background-color: #555;
color: #fff;
}
h1 {
font-size: 22px;
margin: 16px 0;
color: #212121;
}
paper-tabs[grayTab]{
background: #eee;
margin-top: 3%;
margin-bottom: 3%;
}
.flex {
#apply(--layout-horizontal);
}
.flex-horizontal-with-ratios {
#apply(--layout-horizontal);
}
.flexchild {
#apply(--layout-flex);
}
.flex2child {
#apply(--layout-flex-2);
}
.flex3child {
#apply(--layout-flex-3);
}
.flex-center-justified {
#apply(--layout-horizontal);
#apply(--layout-center-justified);
}
.flex-equal-justified {
#apply(--layout-horizontal);
#apply(--layout-justified);
}
.flex-equal-around-justified {
#apply(--layout-horizontal);
#apply(--layout-around-justified);
}
paper-button.gray {
background: #eee;
color: #000;
}
paper-button.gray:hover {
background: #555;
}
paper-button[disabled],
paper-button[toggles][active] {
background: red;
}
</style>
<template>
<div class="card">
<h1>Alta de Protocolos</h1>
<div class="cointainer flex-horizontal-with-ratios">
<div class="flex2child">
<iron-label>Nombre de Protocolo</iron-label>
</div>
<div class="flexchild">
<iron-label>Núm. Visitas</iron-label>
</div>
</div>
<div class="cointainer flex-horizontal-with-ratios">
<div class="flex2child">
<paper-input name="protocol" id="protocol" value="{{protocol}}"></paper-input>
</div>
<div class="flexchild">
<paper-input name="visit" id="visit" value="{{visits}}" prevent-invalid-input allowed-pattern="[0-9]" on-change="visitChanged"></paper-input>
</div>
</div>
<paper-input id="selection" hidden="true" value="{{selected}}"></paper-input>
<!-- Tab's Element-->
<paper-tabs selected="{{selected}}" scrollable no-slide noink grayTab>
<template id="tabs" is="dom-repeat" items="{{tabArrayTest}}" as="tab">
<paper-tab>{{tab.tabName}}</paper-tab>
</template>
</paper-tabs>
<!-- /Tab's Element-->
<!-- iron-pages Element's-->
<iron-pages selected="{{selected}}">
<template id="pages" is="dom-repeat" items="{{tabArrayTest}}" as="tabInput">
<div>
<template id="inputs" is="dom-repeat" items="{{tabInput.inputs}}" as="inp">
<div class="container flex">
<div>
<paper-input id="input" value= "{{inp.value}}" placeholder="{{inp.placeholder}}"></paper-input>
</div>
<div>
<paper-button class="gray" raised on-tap="delInput">Eliminar</paper-button>
</div>
</div>
</template>
<div class="container flex">
<paper-button class="gray" raised on-tap="addInput">Agregar</paper-button>
</div>
</div>
</template>
</iron-pages>
<!-- /iron-pages Element's-->
<div class="container flex-center-justified">
<div>
<paper-button class="gray" raised>Cancelar</paper-button>
<paper-button class="gray" raised>Guardar</paper-button>
</div>
</div>
</div>
</template>
</don-module>
<script>
Polymer({
is: 'protocolo-app',
properties: {
protocol: {
type: String,
value: ""
},
visits:{
type:Number,
value: 3,
notify: true
},
tabArray: {
type: Array,
value: [{value:"visita1"},{value:"visita2"},{value:"visita3"}]
},
tabArrayTest: {
type: Array,
value: [{
tabName:"visita1",
inputs: [{value:"", placeholder:"t1_input1"},{value:"", placeholder:"t1_input2"},{value:"", placeholder:"t1_input3"}]
},
{
tabName:"visita2",
inputs: [{value:"", placeholder:"t2_input1"},{value:"", placeholder:"t2_input1"},{value:"", placeholder:"t2_input1"}]
},
{
tabName:"visita3",
inputs: [{value:"", placeholder:"t3_input1"},{value:"", placeholder:"t3_input1"},{value:"", placeholder:"t3_input1"}]
}]
},
selected:{
type: Number,
value: 0,
},
inputArray: {
type: Array,
value: [{value:"",placeholder:"t1_input1"},{value:"",placeholder:"t1_input2"},{value:"",placeholder:"t1_input3"}]
}
},
observers: [
'test(tabArrayTest.*)'
],
//funcion que agrega input's
addInput: function(){
var sel = this.$.selection.value;
//alert("Tab Seleccionado: " + sel);
this.push('tabArrayTest.'+ sel + '.inputs',[{value:"",placeholder:""}])[0];
},
test: function(){
console.log("Se modifico el array");
},
//funcion que elimina input's
delInput: function(e){
var sel = this.$.selection.value;
this.splice('tabArrayTest.'+ sel + '.inputs',e.model.index,1);
},
creaArrayTabs: function(e){
console.log(this.value);
},
concat: function(v1, v2){
var res = v1 + v2;
alert("Concatenacion: " + res);
//return v1 + v2;
},
//funcion que carga los arrays necesarios para la aplicacion
visitChanged: function(e){
//alert("Valor: " + this.$.visit.value);
//limpiamos el array para agregar las nuevas tabs
this.splice('tabArrayTest',e.model);
//asignamos a la variable max el valor del input
var max = this.$.visit.value;
for (i = 0; i < max; i++) {
//alert("Prueba " + i);
var k = i +1;
this.push('tabArrayTest',{tabName:"Visita " + k, inputs:[{value:"", placeholder:"t"+ k + "_input1"},{value:"", placeholder:"t"+ k + "_input2"},{value:"", placeholder:"t"+ k + "_input3"}]});
//this['inputArray'+ i] = [];
//for (j = 0; j < 3; j++) {
// this.push('inputArray' + i,{value:"",placeholder:"t"+ i + "_input"+j});
//}
}
}
});
</script>

Related

How to set the responsive width of Polymer component inside `<iron-list grid>`

Consider the following code, where <my-item> always has a fixed width of 200px inside <iron-list grid>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Polymer Element Test Case</title>
<!-- Load webcomponents-loader.js to check and load any polyfills your browser needs -->
<script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="bower_components/polymer/polymer-element.html">
<link rel="import" href="bower_components/iron-list/iron-list.html">
</head>
<body>
<h1>iron-list-grid-calc-issue</h1>
<!-- Test case HTML goes here -->
<test-case>
</test-case>
<dom-module id="test-case">
<template>
<iron-list items="[[items]]" grid>
<template>
<div>
<!-- value: [[item.n]] -->
<my-item data="[[item]]"></my-item>
</div>
</template>
</iron-list>
</template>
</dom-module>
<dom-module id="my-item">
<template>
<style>
.content {
width: calc(50% - 32px); /* Not working */
width: 200px;
height: 200px;
line-height: 200px;
text-align: center;
border: 1px solid grey;
box-sizing: border-box;
}
</style>
<div class="container">
<div class="content">
data: [[data.n]]
</div>
</div>
</template>
</dom-module>
<script>
window.addEventListener('WebComponentsReady', function() {
class TestCase extends Polymer.Element {
static get is() {
return 'test-case';
}
static get properties() {
return {
items: {
type: Array,
value: function() {
let items = [];
for (let i=0; i < 10; i++) {
items.push({
n: i,
});
}
return items;
}
},
};
}
}
class MyItem extends Polymer.Element {
static get is() {
return 'my-item';
}
static get properties() {
return {
data: Object,
};
}
}
window.customElements.define(TestCase.is, TestCase);
window.customElements.define(MyItem.is, MyItem);
});
</script>
</body>
</html>
I intend to make <my-item> responsive by always showing 2 <my-item>s per row (which can be stretched) by setting the width of <my-item> with width: calc(50% - 32px). I noticed CSS calc() doesn't seem to work as expected.
How do I set the responsive width of a Polymer component inside <iron-list grid>?
Set the size of the item template's root container element (<div> in this case).
<iron-list items="[[items]]" grid>
<template>
<div style="width: calc(50% - 32px); height: 200px"> <!-- root container element -->
<my-item data="[[item]]"></my-item>
</div>
</template>
</iron-list>
<head>
<base href="https://polygit.org/polymer+v2.3.1/components/">
<script src="webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="iron-list/iron-list.html">
</head>
<body>
<h1>iron-list-grid-calc-issue</h1>
<test-case></test-case>
<dom-module id="test-case">
<template>
<style>
.item {
width: calc(50% - 32px);
height: 200px;
}
</style>
<iron-list items="[[items]]" grid>
<template>
<!-- Set the size of the item template's root container,
which is this `div` element. -->
<div class="item">
<my-item data="[[item]]"></my-item>
</div>
</template>
</iron-list>
</template>
</dom-module>
<dom-module id="my-item">
<template>
<style>
.content {
/* NOTE: The item size is set in the item template
in `iron-list` */
/*width: calc(50% - 32px);*/
/*width: 200px;*/
/*height: 200px;*/
line-height: 200px;
text-align: center;
border: 1px solid grey;
box-sizing: border-box;
}
</style>
<div class="container">
<div class="content">
data: [[data.n]]
</div>
</div>
</template>
</dom-module>
<script>
window.addEventListener('WebComponentsReady', function() {
class TestCase extends Polymer.Element {
static get is() {
return 'test-case';
}
static get properties() {
return {
items: {
type: Array,
value: function() {
let items = [];
for (let i=0; i < 10; i++) {
items.push({
n: i,
});
}
return items;
}
},
};
}
}
class MyItem extends Polymer.Element {
static get is() {
return 'my-item';
}
static get properties() {
return {
data: Object,
};
}
}
window.customElements.define(TestCase.is, TestCase);
window.customElements.define(MyItem.is, MyItem);
});
</script>
</body>
codepen

Set Polymer paper-badge label with JavaScript

How can I set the label of a paper-badge with JavaScript?
I have tried this but is does not work:
Polymer.dom(document.getElementById("id_of_tag")).label = "5";
A more complete code snippet is here:
<script type="text/javascript">
var socket = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/ws");
stompClient = Stomp.over(socket); stompClient.debug = null;
stompClient.connect({}, function(frame) {
stompClient.subscribe("/user/queue",
function(m, h) {
response = JSON.parse(m.body);
badge = Polymer.dom(document.getElementById("notificationsLabel"));
badge.label = "5";
} ,{ "id" : "${currentUserId}" }
);
}, function(e) {
console.log("openWebSocket error", e);
});
</script>
<!-- a lot more stuff -->
<paper-badge id="notificationsLabel" for="notifications" label="0"></paper-badge>
If you are trying to set it inside a Polymer element prefer
this.$.id.label
or if it's inside a dom-repeat or dom-if
this.$$('#id').label
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-badge/paper-badge.html">
<dom-module id="accessing-element">
<template>
<style>
.myDiv {
width: 250px;
height: 40px;
border: 1px solid black;
margin-bottom: 30px;
}
</style>
<div id="insideBadge" class="myDiv">badge inside element</div>
<paper-badge for="insideBadge" id="insideOwnDom" label="1"></paper-badge>
<div on-tap="_changeLabel">Click me to change all labels</div>
</template>
</dom-module>
<script>
Polymer({
is: 'accessing-element',
_changeLabel: function() {
this.$.insideOwnDom.label = 2;
var docLevel = document.getElementById('inSameDoc');
docLevel.label = 3;
var anotherElement = document.querySelector('another-element');
var ele = Polymer.dom(anotherElement.root);
var badge = ele.getEffectiveChildNodes()[3];
badge.label = 4;
// or
// anotherElement.label= 4;
}
})
</script>
<dom-module id="another-element">
<template>
<style>
.myDiv {
width: 250px;
height: 40px;
border: 1px solid black;
margin-bottom: 30px;
}
</style>
<div id="anotherELementsBadge" class="myDiv">badge inside another element</div>
<paper-badge id="anotherElementsDom" for="anotherELementsBadge" label="{{label}}"></paper-badge>
</template>
</dom-module>
<script>
Polymer({
is: 'another-element',
properties: {
label: {
type: Number,
value: 1
}
}
})
</script>
<html>
<head>
<meta charset="UTF-8">
<title>Change labels</title>
</head>
<body>
<style>
.myDiv {
width: 250px;
height: 40px;
border: 1px solid black;
margin-bottom: 30px;
}
</style>
<div style="height:100px;"></div>
<div id="docBadge" class="myDiv">badge at same doc level</div>
<paper-badge for="docBadge" id="inSameDoc" label="1"></paper-badge>
<another-element></another-element>
<accessing-element></accessing-element>
</body>
</html>

Polymer.lazyRegister destroy style while upgrading from, v1.2.3 to v1.4.0

i'm developping an application with Polymer.
My old version was v1.2.3.
I try since this morning to optimize my application about import using the importHref function to load some files on the fly.
I've found that there is a bug (https://github.com/Polymer/polymer/issues/3638) so I tried to update to the last version to have the bugfix (v1.7.0). After upgrading, i seems that some problems occurs with styling.
After some search, i've found that the problem is here when I update from v1.2.3 to v1.4.0 and using
window.Polymer.lazyRegister = true;
It adds some scrollbars (don't find why or where or how), shift some styles, .... and absolutely don't know why.
Does anyone have any idea?
thanks a lot
Edit : add before / after screenshot
edit : add code
index.html
<title>my app</title>
<script src="bower_components/lodash/lodash.js"></script>
<script src="lib/md5/md5.js"></script>
<script src="bower_components/page/page.js"></script>
<link rel="import" href="utils/behaviors/i18n/i18n.html">
<script>
// Setup Polymer options
window.Polymer = {
dom: 'shady',
lazyRegister: true
};
(function() {
'use strict';
var onload = function() {
if (!window.HTMLImports) {
document.dispatchEvent(
new CustomEvent('WebComponentsReady', {bubbles: true})
);
}
};
var webComponentsSupported = (
'registerElement' in document
&& 'import' in document.createElement('link')
&& 'content' in document.createElement('template')
);
if (!webComponentsSupported) {
var script = document.createElement('script');
script.async = true;
script.src = '/bower_components/webcomponentsjs/webcomponents-lite.min.js';
script.onload = onload;
document.head.appendChild(script);
} else {
onload();
}
})();
</script>
<link rel="import" href="bower_components/polymer/polymer.html">
<!-- not paste, but here are the polymer elements papaer-*, iron-*, ... -->
<!-- elements.html is just an external file with all my own elements -->
<link rel="import" href="elements/elements.html">
<link href="res/css/app.css" rel="stylesheet"/>
<style>
body {
margin: 0;
height: 100vh;
}
</style>
</head>
<body class="layout vertical">
<template is="dom-bind" id="myApp">
<my-application id="application"></my-application>
</template>
</body>
</html>
my-application.html
<dom-module id="my-application">
<style>
:host {
height : 100%;
}
iron-pages {
height : 100%;
}
#popin {
position: absolute;
display: none;
z-index: 100;
}
#mainCtn {
height: 100%;
width: 100%;
}
my-loader-synchronizer {
z-index: 100;
height: 100%;
width: 100%;
position: absolute;
top: 0px;
left: 0px;
}
</style>
<template>
<div id="mainCtn" on-click="_onMainCtnClick">
<iron-pages attr-for-selected="data-route" selected="{{route}}">
<my-login id="log" data-route="login"></my-login>
<paper-header-panel data-route="dashboard">
<my-header class="paper-header"></my-header>
<my-dashboard id="dashboard" class="fit"></my-dashboard>
</paper-header-panel>
</iron-pages>
<my-dialog id="dialog"></my-dialog>
<my-loader-synchronizer id="loaderSynchronizer" hidden$="{{!synchro}}"></my-loader-synchronizer>
<div id="popin"></div>
<my-dialog-selector id="dialogSelector"></my-dialog-selector>
</div>
<my-toast id="toast"></my-toast>
</template>
<link rel="import" href="../../utils/behaviors/storage/ramCache.html">
<link rel="import" href="../../utils/behaviors/session/session.html">
<link rel="import" href="../../utils/behaviors/communication/applicationCommunication.html">
<script>
Polymer({
is: 'my-application',
properties: {
"synchro" : {
"type" : Boolean,
"value" : false
},
"amIConnected" : {
"type" : Boolean,
"value" : false
},
animationConfig : {
type : Object,
value : function () {
return {
"fadeOut" : [{
name : 'fade-out-animation',
node : this.$$("#loaderSynchronizer")
}],
}
}
}
},
behaviors : [applicationCommunication, Polymer.NeonAnimationRunnerBehavior],
listeners : {
"neon-animation-finish": "fadeComplete"
},
ready: function ready() {
// all listeners are registered here
this.addEventListener("mousemove", this._onGlobalMouseMove.bind(this));
this._disconnectTimeout = setTimeout(this._disconnect.bind(this), 3600000);
},
_onGlobalMouseMove : function _onGlobalMouseMove (e) {
if (this.amIConnected == true) {
if (e.movementX != 0 || e.movementY != 0) {
clearTimeout(this._disconnectTimeout);
this._disconnectTimeout = setTimeout(this._disconnect.bind(this), 3600000);
}
}
},
_disconnect : function _disconnect () {
clearTimeout(this._disconnectTimeout);
session.getInstance().disconnect();
},
attached : function () {
page("/", function () {
this.route = "login";
}.bind(this));
page("/dashboard", function () {
this.amIConnected = true;
this.synchro = true;
this.$$("#loaderSynchronizer").synchronizeData();
this.$.dashboard.onShow();
this.route = "dashboard";
}.bind(this));
page({
hashbang: true
});
},
fadeComplete : function fadeComplete () {
this.synchro = false;
},
_closeLoaderSynchronizer : function _closeLoaderSynchronizer () {
this.cancelAnimation();
this.playAnimation("fadeOut");
},
});
</script>
</dom-module>
my-login.html
<dom-module id="my-login">
<style>
:host {
font-family : "Roboto-Bold";
font-size: 16pt;
--paper-input-container-underline: {
background-color: var(--paper-grey-400);
}
--paper-input-container-label: {
color: var(--paper-grey-400);
}
--paper-input-container-input: {
color: var(--paper-black);
}
--paper-input-container-focus-color: var(--paper-blue-600);
}
#container {
height: 100%;
width: 100%;
background-image: url("../../res/img/loginBack.jpg");
background-size: cover;
background-color: white;
}
#logomyCtn {
z-index: 100;
position: absolute;
margin-left: 80px;
margin-top: 150px;
}
#logomyCtn iron-image {
--iron-image-width: 16vw;
--iron-image-height: 10vw;
}
paper-card {
--paper-card-header: {
#apply(--layout-horizontal);
#apply(--layout-end);
background-color: var(--paper-blue-600);
height: 100px;
}
--paper-card-content: {
margin-right: 50px;
margin-left: 50px;
}
--paper-card-actions: {
#apply(--layout-vertical);
#apply(--layout-center);
}
--paper-card-header-text: {
color: #fff;
position: absolute;
font-family: "Roboto-Light";
bottom: 0px;
left: 0px;
}
--paper-card-header-image: {
width: 146px;
height: 32px;
margin-left: auto;
margin-right: auto;
margin-bottom: 16px;
}
}
paper-button.blue {
font-size: 12pt;
background: var(--paper-blue-600);
color: #fff;
font-family: "Roboto-Medium";
margin-top: 10px;
width: 14vw;
}
paper-button.small {
font-size: 13px;
text-transform: lowercase;
--paper-button-ink-color: transparent;
font-family: "Roboto-Light";
color: var(--paper-grey-700);
}
paper-button.pwd {
font-size: 13px;
text-transform: lowercase;
--paper-button-ink-color: transparent;
font-family: "Roboto-Light";
color: var(--paper-grey-700);
}
#logoContainer {
width: 100%;
height: 20%;
#apply(--layout-horizontal);
#apply(--layout-center);
}
iron-image {
margin-left: auto;
margin-right: auto;
}
#loginContainer {
width: 400px;
height: 60%;
margin-left: auto;
margin-right: auto;
#apply(--layout-vertical);
#apply(--layout-center-justified);
}
#versionContainer {
width: 100%;
height: 20%;
#apply(--layout-horizontal);
#apply(--layout-end);
}
#version {
margin-left: auto;
margin-right: auto;
margin-bottom: 25px;
font-family: "Roboto-Light";
font-size: 13px;
color: var(--paper-grey-700);
}
</style>
<template>
<div id="container">
<div id="logomyCtn">
<iron-image src="../../res/img/logo.png"></iron-image>
</div>
<div id="logoContainer"></div>
<div id="loginContainer">
<paper-card elevation="1" image="../../res/img/logologin.png">
<div class="card-content" on-keypress="_keyHandler">
<paper-input id="login" label="[[i18n('uid')]]"></paper-input>
<paper-input id="pwd" label="[[i18n('pwd')]]" type="password"></paper-input>
<paper-input id="server" label="[[i18n('server')]]"></paper-input>
</div>
<div class="card-actions">
<paper-button class="blue" on-click="_login">[[i18n("connect")]]</paper-button>
<paper-button class="pwd" on-click="_openPwd">[[i18n("forgotPwd")]]</paper-button>
</div>
</paper-card>
</div>
<div id="versionContainer">
<div id="version">
[[i18n("version")]]
<paper-button class="small" on-click="_openContact">[[i18n("contact")]]</paper-button>
</div>
</div>
<my-dialog id="dialog"></my-dialog>
</div>
</template>
<link rel="import" href="../../utils/behaviors/communication/loginCommunication.html">
<link rel="import" href="../../utils/behaviors/storage/localCache.html">
<link rel="import" href="../../utils/behaviors/storage/sessionCache.html">
<script>
Polymer({
is: 'my-login',
// don't paste code, only classical login code
});
</script>
</dom-module>
my-loader-synchronizer.html
<dom-module id="my-loader-synchronizer">
<style>
:host {
display: block;
background-image: url("../../res/img/loginBack.jpg");
background-size: cover;
}
#mainCtn {
height: 100%;
width: 100%;
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#loading {
margin-top: 16px;
font-size: 20px;
font-family: "Roboto";
color: var(--paper-grey-700);
}
paper-progress {
width: 50%;
--paper-progress-active-color: var(--paper-blue-500);
}
#logoCtn {
z-index: 100;
position: absolute;
margin-left: 80px;
margin-top: 150px;
}
#logoCtn iron-image {
--iron-image-width: 16vw;
--iron-image-height: 10vw;
}
</style>
<template>
<div id="mainCtn">
<paper-progress class="transiting" value="{{currentResponse}}" max="{{totalData}}"></paper-progress>
<div id="loading">[[i18n("loading")]]</div>
</div>
<div id="logoCtn">
<iron-image src="../../res/img/logo.png"></iron-image>
</div>
</template>
<link rel="import" href="../../utils/behaviors/storage/ramCache.html">
<link rel="import" href="../../utils/behaviors/storage/sessionCache.html">
<link rel="import" href="../../utils/behaviors/entities/entitiesParser.html">
<link rel="import" href="../../utils/behaviors/communication/loaderSynchronizerCommunication.html">
<script>
Polymer({
is: 'my-loader-synchronizer',
created : function () {
this.i18n = i18n.getInstance();
},
properties: {
"data" : {
"type" : Array,
"value" : function () {
return [{
"entity" : "UserEntity",
"okCb" : this.usersCallback.bind(this),
"koCb" : this.usersCallbackError.bind(this)
},{
"entity" : "VehicleGroup",
"okCb" : this.vehicleGroupCallback.bind(this),
"koCb" : this.vehicleGroupCallbackError.bind(this)
},{
// multiple definitions
}]
}
}
},
behaviors : [loaderSynchronizerCommunication, entitiesParser],
ready: function ready() {
this.ramCache = ramCache.getInstance();
this.sessionCache = sessionCache.getInstance();
},
synchronizeData : function synchronizeData () {
this.totalData = this.data.length;
this.currentResponse = 0;
var i = this.data.length,
params = {
"token" : this.sessionCache.get("token")
};
while (i--) {
if (this.data[i].entity) {
var entity = this.data[i];
if (!entity.type || entity.type == "entity") {
this.prepareEntityRequest(entity.entity, params, entity.okCb, entity.koCb);
} else if (entity.type == "light") {
this.prepareLightRequest(entity.entity, params, entity.okCb, entity.koCb);
}
}
}
},
_updateRoutine : function _updateRoutine () {
var i = this.routine.length,
params = {
"token" : this.sessionCache.get("token")
};
while (i--) {
if (this.routine[i].entity) {
var entity = this.routine[i];
this.prepareEntityRequest(entity.entity, params, entity.okCb, entity.koCb);
}
}
},
_changeProgress : function _changeProgress (entity) {
this.currentResponse++;
if (this.currentResponse == this.totalData) {
this.timeoutCtrl = setTimeout(this._fireClose.bind(this), 1000);
}
},
_fireClose : function _fireClose () {
clearTimeout(this.timeoutCtrl);
// will be catch by my-application
this.fire("close-loader-synchronizer");
},
/* CALLBACK */
/*********/
/* USERS */
/*********/
usersCallback : function usersCallback (response) {
this.parseUsers(response);
this._changeProgress("UserEntity");
},
usersCallbackError : function usersCallbackError (error) {
this.fire("show-toast", {"type" : "error", "text" : "userEntityError"});
},
/*****************/
/* VEHICLES GROUP*/
/*****************/
vehicleGroupCallback : function vehicleGroupCallback (response) {
this.parseVehicleGroup(response);
this._changeProgress("VehicleGroup");
},
vehicleGroupCallbackError : function vehicleGroupCallbackError (error) {
this.fire("show-toast", {"type" : "error", "text" : "vehicleGroupEntityError"});
},
});
</script>
</dom-module>
my-header.html
<dom-module id="my-header">
<style>
:host {}
paper-toolbar {
--paper-toolbar-background: var(--paper-blue-500);
}
.first {
font-family : "Roboto-Bold";
}
.last {
font-family: "Roboto-Light";
}
</style>
<template>
<paper-toolbar>
<my-menu-button on-tap="_tapToggleButton"></my-menu-button>
<div class="title">[[i18n("product")]] [[i18n("version")]]</div>
</paper-toolbar>
</template>
<script>
Polymer({
is: 'my-header',
created : function () {
this.i18n = i18n.getInstance();
},
properties: {},
ready: function ready() {},
_tapToggleButton : function _tapToggleButton () {
this.fire("toggle-drawer");
},
});
</script>
</dom-module>
my-dashboard.html
<dom-module id="my-dashboard">
<style>
:host {
font-family : "Roboto";
}
</style>
<template>
<paper-drawer-panel id="drawerPanel" responsive-width="1300px">
<my-dashboard-left-panel drawer id="leftpanel"></my-dashboard-left-panel>
<my-dashboard-content main id="content"></my-dashboard-content>
</paper-drawer-panel>
</template>
<link rel="import" href="../../utils/behaviors/communication/childNotifications.html">
<script>
Polymer({
is: 'my-dashboard',
properties: {},
behaviors : [childNotifications, Polymer.IronResizableBehavior],
ready: function ready() {},
/************************/
/*** PUBLIC FUNCTIONS ***/
/************************/
onShow : function onShow () {
this.notifyChild("showDashboard");
},
/**
* toggle left panel
**/
toggleDrawer : function toggleDrawer () {
var responsiveWidth = parseInt(this.$.drawerPanel.responsiveWidth.replace("px", ""));
if (responsiveWidth < this.$.drawerPanel.offsetWidth) {
this.$.drawerPanel.forceNarrow = !this.$.drawerPanel.forceNarrow;
setTimeout(function () {
clearInterval(this.toto)
}.bind(this), 1000);
setInterval(function () {
this.$.content.resize();
// notify children that they need to resize
this.notifyResize();
}.bind(this), 100)
} else {
this.$.drawerPanel.togglePanel();
}
}
});
</script>
</dom-module>
I past only files which seems to be important.
So, how it works?
At first, when display my-login will be display to allow user to log in (routing is made with page.js)
There is no problem on the login screen.
When user is logged, route to /dashboard, and display the paper-header-panel and my-loader-synchronizer to sync all data and display a progress bar. When all is done, the synchronizer will be hide to make the paper-header-panel visible (screenshot are take at this moment)
When the synchronize is shown, the styles problems start.
If you need more files, don't hesitate.
thanks a lot !

Polymer 1.x: How to animate custom elements using neon-animation cascaded-animation

This plunk demonstrates the behavior I am trying to achieve.
This plunk demonstrates my problem. Which is that the individual <li items do not perform their cascaded-animation behavior. All I did was to substitute a custom element I called <content-el> in the repeater and change the appropriate node definitions.
Please answer by providing a working plunk that animates the individual <content-el> nodes.
http://plnkr.co/edit/ZzG4lDvl4V32Bod36208?p=preview
<link href="content-el.html" rel="import">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link rel="import" href="app-layout/app-grid/app-grid-style.html">
<link rel="import" href="neon-animation/neon-animation.html">
<link rel="import" href="paper-card/paper-card.html">
<dom-module id="x-app">
<template>
<style include="app-grid-style">
:host {
display: block;
--app-grid-columns: 2;
--app-grid-gutter: 10px;
--paper-icon-button-ink-color: white;
}
.item {
height: 250px;
position: relative;
background-color: white;
background-size: cover;
background-position: center center;
}
</style>
<button on-tap="play">Play Animation</button>
<div class="centered-container">
<ul class="app-grid">
<template id="items"
is="dom-repeat"
items="[1,2,3,4,5,6]"
>
<li class="item"
style="background-image: url(http://fakeimg.pl/800x800/0079D8/fff/?text=[[item]]);"
>
</li>
</template>
</ul>
</div>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'x-app',
behaviors: [
Polymer.NeonAnimationRunnerBehavior,
],
properties: {
animationConfig: {
type: Object,
value: function() {
return {
'entry': [
{
name: 'slide-from-right-animation',
node: this,
}, {
name: 'cascaded-animation',
animation: 'scale-up-animation',
timing: {
delay: 500,
},
},
],
};
},
},
},
attached: function() {
this.async(function() {
var nodeList = Polymer.dom(this.root).querySelectorAll('li.item');
this.animationConfig['entry'][1].nodes = Array.prototype.slice.call(nodeList);
//console.log(this.animationConfig['entry'][1].nodes);
this.playAnimation('entry');
}.bind(this), 500); // https://github.com/Polymer/polymer/issues/2500
},
play: function() {
this.playAnimation('entry');
},
});
})();
</script>
</dom-module>
<dom-module id="content-el">
<template>
<style>
:host {
box-sizing: border-box;
display: block;
}
</style>
http://plnkr.co/edit/2bijfuGjC7NjIAPhMIj4?p=preview

How to use core-scroll-header-panel with core-list

I'm wanting to use core-scroll-header-panel with core-list so that as I scroll the list the header condenses and disappears. Particularly for mobile that will maximise the space for the list. I took the demo and tried to adapt it for a core-list but failed to get it to scroll the header off the page. My attempts are at http://jsbin.com/sivuvu
Any help appreciated.
Here's one possible solution:
<!doctype html>
<html>
<head>
<script src="https://www.polymer-project.org/0.5/webcomponents.min.js"></script>
<link rel="import" href="https://www.polymer-project.org/0.5/components/polymer/polymer.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-scroll-header-panel/core-scroll-header-panel.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-list/core-list.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-header-panel/core-header-panel.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-toolbar/core-toolbar.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/core-icon-button/core-icon-button.html">
<style shim-shadowdom>
body {
font-family: sans-serif;
color: #333;
}
/* background for toolbar when it is at its full size */
core-scroll-header-panel::shadow #headerBg {
background-image: url(https://www.polymer-project.org/0.5/components/core-scroll-header-panel/demos/images/bg9.jpg);
}
/* background for toolbar when it is condensed */
core-scroll-header-panel::shadow #condensedHeaderBg {
background-color: #f4b400;
}
core-toolbar {
color: #f1f1f1;
fill: #f1f1f1;
background-color: transparent;
}
.title {
-webkit-transform-origin: 0;
transform-origin: 0;
font-size: 40px;
}
.content {
padding: 8px;
background-color: #eee;
}
core-list {
border: solid 1px red;
margin: 10px;
overflow: hidden;
}
div.foo, core-list {
border: solid 1px blue;
margin: 10px;
}
div.row {
height: 80px;
border: solid 1px green;
margin: 3px;
text-align: center;
}
</style>
</head>
<body unresolved fullbleed>
<template is="auto-binding" id="page-template">
<core-scroll-header-panel condenses fit>
<core-toolbar class="tall">
<core-icon-button icon="arrow-back"></core-icon-button>
<div flex></div>
<core-icon-button icon="search"></core-icon-button>
<core-icon-button icon="more-vert"></core-icon-button>
<div class="bottom indent title">Title</div>
</core-toolbar>
<div class="content" flex>
<core-list data="{{data}}" flex>
<template>
<div class="row">
List row: {{index}}, User data from model: {{model.name}}
</div>
</template>
</core-list>
</div>
</core-scroll-header-panel>
</template>
<script>
var t = document.querySelector('#page-template');
t.data = [];
for (i = 0; i < 30; i++) {
t.data.push({name: 'Bob'});
}
t.addEventListener('template-bound', function() {
// custom transformation: scale header's title
var titleStyle = document.querySelector('.title').style;
addEventListener('core-header-transform', function(e) {
var d = e.detail;
var m = d.height - d.condensedHeight;
var scale = Math.max(0.75, (m - d.y) / (m / 0.25) + 0.75);
titleStyle.transform = titleStyle.webkitTransform =
'scale(' + scale + ') translateZ(0)';
});
});
</script>
</body>
</html>
A few changes that I made to your code: instead of wrapping the <core-list> in a custom Polymer element definition, I just include it as part of the main page, but the page itself is wrapped in <template is="auto-binding">, giving you access to all the same template syntactic sugar you'd get from a custom element. The main other thing was to set overflow: hidden on the <core-list>, and rely on the scrollbar from the <core-scroll-header-panel> to scroll the list's content.