Only ready lifecycle callback fires in Polymer 2 - polymer

When I create a Polymer 2.0 element, only the ready lifecycle callback seems to fire, and I can't work out why. For example, I have this Polymer element:
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<dom-module id="flip-four-board">
<script>
class FlipFourBoard extends Polymer.Element {
static get is() { return "flip-four-board"; }
created() {
super.created();
console.log("created");
}
ready() {
super.ready();
console.log("ready");
}
attached() {
super.attached();
console.log("attached");
}
detached() {
super.detached();
console.log("detached");
}
}
customElements.define(FlipFourBoard.is, FlipFourBoard);
</script>
</dom-module>
But when I insert it into a page like this:
<!DOCTYPE html>
<html>
<head>
<title>Flip Four Board Tests</title>
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../flip-four-board.html">
<style type="text/css">
html, body {
width: 95%;
height: 95%;
}
</style>
</head>
<body>
<flip-four-board></flip-four-board>
</body>
</html>
The console only reads:
Why is only the ready callback firing?

Polymer 2.0 introduces several lifecycle callback changes, including the replacement of all but one of the original callbacks (i.e., ready) in the class-based element definitions. The legacy callbacks are still available when using the Polymer factory method in 2.0.
1.x (legacy) | 2.x
----------------------|-----------------------------
created | constructor
attached | connectedCallback
detached | disconnectedCallback
attributeChanged | attributeChangedCallback
ready | ready
So, your class should look similar to this:
class FlipFourBoard extends Polymer.Element {
static get is() { return "flip-four-board"; }
constructor() {
super();
console.log("created");
}
ready() {
super.ready();
console.log("ready");
}
connectedCallback() {
super.connectedCallback();
console.log("attached");
}
disconnectedCallback() {
super.disconnectedCallback();
console.log("detached");
}
}
demo

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.

how to use data from one page in polymer 2.0 in another

I have a html file which makes a rest call and gets data in an array. How can I use this another file. I want to be able to access and manipulate the data and print each element in the array on click of next button. my-assessment.html contains the data loaded and my-quiz.html should contain the next and previous button to loop through the data.
my-assessment.html
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="../bower_components/polymer-simple-slider/simple-slider.html">
<link rel="import" href="../bower_components/promise-polyfill/promise-polyfill-lite.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="my-assessment">
<template>
<button on-click="getAssessment">Load Assessment</button>
<!--Check the url is correct ! And last responce property should be {{}} instead [[]] (as up way data binding) -->
<iron-ajax
id="requestRepos"
url="http://192.168.178.31:8080/demo/assessment"
handle-as="json"
last-response="{{repos}}"
</iron-ajax>
</template>
<script>
class Assessment extends Polymer.Element {
static get is() { return 'my-assessment'; }
static get properties() {
return {
repos: {
type : Array,
observer : 'isQuestionsLoaded'
}
}
}
// set this element's employees property
constructor() {
super();
}
isQuestionsLoaded(q) {
if (q) {
console.log('loaded questions', q); // questions are loaded.
}
this.questions = q;
}
getAssessment() {
this.$.requestRepos.generateRequest();
}
}
window.customElements.define(Assessment.is, Assessment);
</script>
</dom-module>
my-quiz.html
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="../bower_components/polymer-simple-slider/simple-slider.html">
<link rel="import" href="../bower_components/promise-polyfill/promise-polyfill-lite.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="my-assessment.html">
<dom-module id="my-quiz">
<template>
<my-assessment>
</my-assessment>
</template>
<script>
class Quiz extends Polymer.Element {
static get is() { return 'my-quiz'; }
static get properties() {
return {
index: {
type: Number,
value: 0
}
}
}
// set this element's employees property
constructor() {
super();
}
}
window.customElements.define(Quiz.is, Quiz);
</script>
</dom-module>
In your case that is shown above the two elements have child parent relation to each other. The element my-quiz contains the element my-assessment. Passing the data up from it's child element can be done with two way data binding. Therefor you will have to add the notify:true to your repos property and use the two way data binding syntax as shown in my example.
Child elements properties:
static get properties() {
return {
repos: {
type : Array,
notify: true,
observer : 'isQuestionsLoaded'
}
}
}
Parent Element:
<dom-module id="my-quiz">
<template>
<my-assessment repo-data="{{repos}}"></my-assessment>
</template>
<script>
class Quiz extends Polymer.Element {
static get is() { return 'my-quiz'; }
static get properties() {
return {
repoData: {
type: Array,
observer: '_dataChanged'
}
}
}
constructor() {
super();
}
_dataChanged(data) {
console.log('Data changed:', data)
}
}
window.customElements.define(Quiz.is, Quiz);
</script>
</dom-module>
As you can see I have used the two way data binding syntax {{}} to get the data that is send up from your child element. Changes will be observed and logged in the console.
To read more about this you can take a look in the Polymer documentation

Polymer 2.0 iron-form response trigger dom-if

How do I use the response data from iron-form to trigger the dom-if template? I want to show the template if there was data was returned. This code is not working. What am I doing wrong here?
<link rel="import" href="../components/polymer/polymer-element.html">
<link rel="import" href="../components/polymer/lib/elements/dom-if.html">
<link rel="import" href="../components/iron-form/iron-form.html">
<dom-module id="a-tag">
<template>
<iron-form>
<form action="/" method="get">
<input name="test">
<button></button>
</form>
</iron-form>
<template class="iftemplate" is="dom-if" if="[[data]]">
<p>HELLO</p>
</template>
</template>
<script>
class ATag extends Polymer.Element {
static get is() {return 'a-tag'}
ready() {
super.ready()
this.shadowRoot.querySelector('iron-form').addEventListener('iron-form-response', (event) => {
this.shadowRoot.querySelector('.iftemplate').data = event.detail.response
})
}
}
customElements.define(ATag.is, ATag)
</script>
</dom-module>
You are doing many wrong things here,
first I would advice to add an id to the form element iron-form so you can point easily in your Polymer element's code.
<iron-form id="my-form">
...
</iron-form>
and add the event listener like that :
this.$['my-form'].addEventListener('iron-form-response', ...);
Also you are trying to add a property data to the template dom-if I don't understand why. [[data]] references a property in your element's scope. You have to define this property in the correct section.
static get properties () {
return {
data: {
type: String,
value: ''
}
};
}
and in your event listener callback :
ready() {
super.ready()
this.$['my-form'].addEventListener('iron-form-response', (event) => {
// this.data = event.detail.response;
this.data = 'some data'; // for testing
});
}

Multiple polymer 2 elements with independent properties?

I have a question to my custom polymer element. First, I made an element with a simple paper-input. My problem is, that I don't know, how to use this element as an "independent" element. My example is here in this jsfiddle. Type in the first input "asd" and hit Enter and then in the second input "asd" and hit Enter. You can see, that both elements are sharing the properties (console log "-1" not found in array and second log will be "1")
<!doctype html>
<html>
<head>
<title>2.0 preview elements</title>
<base href="http://polygit.org/polymer+v2.0.0-rc.4/webcomponentsjs+webcomponents+v1.0.0-rc.6/shadycss+webcomponents+1.0.0-rc.2/paper*+polymerelements+:2.0-preview/iron*+polymerelements+:2.0-preview/app*+polymerelements+:2.0-preview/neon*+polymerelements+:2.0-preview/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-input/paper-input.html">
</head>
<body>
<input-test></input-test>
<input-test></input-test>
<dom-module id="input-test">
<template>
<paper-input value="{{aValue}}" on-keydown="_keydown"></paper-input>
</template>
<script>
window.addEventListener('WebComponentsReady', function() {
class InputTest extends Polymer.Element {
static get is() {
return 'input-test';
}
static get properties() {
return {
aValue: {
type: String,
value: ''
},
_inputStore: {
type: Array,
value: []
}
};
}
_keydown(event) {
const keyCode_enter = '13';
if (event.keyCode == keyCode_enter) {
console.log(this._inputStore.indexOf(this.aValue))
this.push('_inputStore', this.aValue);
}
}
}
customElements.define(InputTest.is, InputTest);
})
</script>
</dom-module>
</body>
</html>
What can I do, to have independent properties?
Thanks!
I found the answer.
The problem is the default value declaration of the array.
_inputStore: {
type: Array,
value: function () {
return [];
}
}
This code solves the problem.

Polymer deep path binding

In Polymer how do I databind to a Deep path property like shown in the example below
<!doctype html>
<html>
<head>
<script src='bower_components/webcomponentsjs/webcomponents.min.js'></script>
<link rel='import' href='bower_components/polymer/polymer.html'/>
</head>
<body>
<dom-module id='base-page'>
<template>
<input type='button' on-click='click'>
<div>{{item.mydeepproperty}}</div>
</template>
</dom-module>
<script>
Polymer({
is: 'base-page',
properties: {
item: {
type: Object,
value: function() { return { mydeepproperty: 'default' } }
}
},
click: function() {
this.item.mydeepproperty = 'woohoo';
}
});
</script>
<base-page></base-page>
</body>
Example also found here:
http://jsbin.com/qonedeleho/1/edit?html,output
Cheers
When updating a sub-property of an object, you need to be more explicit in your code to force a path change notification and either use the this.set() or this.notify() function:
click: function() {
this.set('item.mydeepproperty', 'woohoo');
}