Polymer, how to get url params in page.js into polymer element? - polymer

I want to make a single page application. When I go to path like localhost/person-info/101, how can I get the URL params using page.js into a Polymer element?
I have to use these params to select or change data in the person-info element before using neon-animated-page to change page
Contents of app.js:
window.addEventListener('WebComponentsReady', function () {
var app = document.querySelector('#app');
page('/', home);
page('/person-info/:user', showPersonInfo);
page({
hashbang: true
});
function home() {
app.route = 'index';
console.log("app route" + app.route);
console.log("home");
}
function showPersonInfo(data) {
console.log(data);
console.log(data.params.user);
app.params = data.params;
app.route = 'person-info';
}
});
And my Polymer element person-info.html
<link rel="import" href="bower_components/iron-list/iron-list.html">
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/paper-toolbar/paper-toolbar.html">
<link rel="import" href="bower_components/paper-icon-button/paper-icon-button.html">
<script type="text/javascript" src="bower_components/jquery-2.1.4.min/index.js"></script>
<script src="js/app.js"></script>
<dom-module id="person-info">
<style>
:host {
display: block;
font-family: sans-serif;
#apply(--layout-fit);
#apply(--layout-vertical);
}
.toolbar {
background: #3f78e3;
}
a {
color:#FFF;
}
</style>
<template id="person-info">
<paper-toolbar class="toolbar">
<a href="/">
<paper-icon-button icon="icons:arrow-back"></paper-icon-button>
</a>
<div>test</div>
<div>test</div>
</paper-toolbar>
<content></content>
</template>
<script>
Polymer({
is: 'person-info',
ready: function () {
console.log("person-info page");
this.testdd = "adisak";
console.log("user ---->"+this.params);
console.log(this);
},
properties: {
dataindex: String
}
});
</script>
</dom-module>

Variable app is global, so if you bind a data to app.params from your route than you can access it everywhere using app.params. Or just access your element and set the properties on your element like below
function showPersonInfo(data){
var personInfo=document.querySelector('person-info');
personInfo.user=data.params;
app.route = 'person-info';
}
From your person-info element you can access by using this.user but i think you need to set the property user on element properties.

Related

How to addEventListener to Polymer 2.0 iron-forms loaded with iron-ajax within dom-repeat template

I have been using the following syntax to edit iron-form requests before submitting in Polymer 2.0:
connectedCallback() {
super.connectedCallback();
someForm.addEventListener('iron-form-presubmit, function() {...})
}
Now I want to load multiple iron-forms within a dom-repeat, each with the same iron-form-presubmit function. The number and content of the forms are loaded from the server using iron-ajax. I intended to loop through all the forms and add the event listener but it seems when I call the following, the forms have not yet loaded so allForms is empty.
HTML:
<iron-ajax auto
id="requestSchedules"
url="/api/v2/schedules"
handle-as="json"
on-response="handleApiResponse"
last-response="{{schedules}}">
</iron-ajax>
<dom-repeat items="[[schedules]]">
<template>
<paper-card heading="Schedule">
<div class="card-content">
<iron-form id="scheduleForm[[item.id]]">
...
Javascript:
connectedCallback() {
super.connectedCallback();
var allForms = this.shadowRoot.querySelectorAll("iron-form");
// here allForms = []
...
}
Inspecting the shadow DOM with a break-point at this point shows the dom-repeat template has not loaded. Is there a way I can wait until the page has completed loading or possibly another way to accomplish the same thing?
You could listen to <dom-repeat>'s dom-change event, which occurs when the template contents change. The event handler could then use querySelectorAll to get a reference to the <iron-form>s:
template:
<dom-repeat on-dom-change="_onDomRepeatChange">
script:
_onDomRepeatChange(e) {
const forms = this.shadowRoot.querySelectorAll('iron-form');
Array.from(forms).forEach(form => {
form.addEventListener('iron-form-presubmit', function() {
this.request.method = 'post';
this.request.params['foo'] = true;
});
});
}
window.addEventListener('WebComponentsReady', () => {
class XFoo extends Polymer.Element {
static get is() { return 'x-foo'; }
_onDomRepeatChange(e) {
const forms = this.shadowRoot.querySelectorAll('iron-form');
Array.from(forms).forEach(form => {
form.addEventListener('iron-form-presubmit', function() {
this.request.method = 'post';
this.request.params['foo'] = true;
});
form.addEventListener('iron-form-response', e => {
const response = e.detail.response;
this.formResponse = JSON.stringify(response, null, 2);
});
});
}
}
customElements.define(XFoo.is, XFoo);
});
<head>
<base href="https://cdn.rawgit.com/download/polymer-cdn/2.6.0.2/lib/">
<script src="webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="iron-ajax/iron-ajax.html">
<link rel="import" href="iron-form/iron-form.html">
<link rel="import" href="paper-card/paper-card.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<iron-ajax auto
id="requestSchedules"
url="https://httpbin.org/anything"
method="POST"
handle-as="json"
content-type="application/json"
body='[{"id":1, "x":1},{"id":2, "x":2}]'
last-response="{{schedules}}">
</iron-ajax>
<template is="dom-repeat" items="[[schedules.json]]" on-dom-change="_onDomRepeatChange">
<paper-card heading="Schedule">
<div class="card-content">
<iron-form id="scheduleForm[[item.id]]">
<form action="https://httpbin.org/post">
<input name="name" type="text" placeholder="Name">
<button>Submit</button>
</form>
</iron-form>
</div>
</paper-card>
</template>
<pre>[[formResponse]]</pre>
</template>
</dom-module>
</body>
Alternatively, you could use an annotated event listener on <iron-form>:
template:
<iron-form on-iron-form-presubmit="_onIronFormPresubmit">
script:
_onIronFormPreSubmit(e) {
const ironForm = e.composedPath()[0];
ironForm.request.method = 'post';
ironForm.request.params['foo'] = true;
}
window.addEventListener('WebComponentsReady', () => {
class XFoo extends Polymer.Element {
static get is() { return 'x-foo'; }
_onIronFormPreSubmit(e) {
const ironForm = e.composedPath()[0];
ironForm.request.method = 'post';
ironForm.request.params['foo'] = true;
}
_onIronFormResponse(e) {
const response = e.detail.response;
this.formResponse = JSON.stringify(response, null, 2);
}
}
customElements.define(XFoo.is, XFoo);
});
<head>
<base href="https://cdn.rawgit.com/download/polymer-cdn/2.6.0.2/lib/">
<script src="webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="iron-ajax/iron-ajax.html">
<link rel="import" href="iron-form/iron-form.html">
<link rel="import" href="paper-card/paper-card.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<iron-ajax auto
id="requestSchedules"
url="https://httpbin.org/anything"
method="POST"
handle-as="json"
content-type="application/json"
body='[{"id":1, "x":1},{"id":2, "x":2}]'
last-response="{{schedules}}">
</iron-ajax>
<template is="dom-repeat" items="[[schedules.json]]">
<paper-card heading="Schedule">
<div class="card-content">
<iron-form id="scheduleForm[[item.id]]"
on-iron-form-presubmit="_onIronFormPreSubmit"
on-iron-form-response="_onIronFormResponse">
<form action="https://httpbin.org/post">
<input name="name" type="text" placeholder="Name">
<button>Submit</button>
</form>
</iron-form>
</div>
</paper-card>
</template>
<pre>[[formResponse]]</pre>
</template>
</dom-module>
</body>

polymer google-map-point in nested dom-repeat stops refreshing

The poly lines works for a while and then stop refreshing. The marker tags keep refreshing properly. The poly lines refresh if I hit the browser refresh button. How can I fix this? I need this to keep refreshing without hitting browser refresh button. The new data is obtained by using iron-ajax and an http GET.
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/google-map/google-map.html">
<link rel="import" href="../../bower_components/google-map/google-map-point.html">
<link rel="import" href="../../bower_components/google-map/google-map-poly.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="ra-app">
<template>
<style>
:host {
display: block;
}
google-map {
display: block;
height: 100vh;
width: 100%;
text-align: center;
font-size: 1.2em;
}
</style>
<google-map latitude="45.559" longitude="-122.65" version="3.exp" zoom="12" >
<template is="dom-repeat" items="[[marker_data]]" as="vehicle">
<google-map-marker icon=[[vehicle.icon]]
latitude=[[vehicle.current_lat]] longitude=[[vehicle.current_lon]] title=[[vehicle.text]]>
</google-map-marker>
<google-map-poly>
<template is="dom-repeat" items="[[vehicle.recent_positions]]" as="location">
<google-map-point latitude=[[location.lat]] longitude=[[location.lon]]></google-map-point>
</template>
</google-map-poly>
</template>
<google-map-marker icon="http://maps.google.com/mapfiles/kml/shapes/bus.png"
latitude=45.54843 longitude=-123.60 title="arrggghhhh!!!!!">
<img src="http://maps.google.com/mapfiles/kml/shapes/bus.png">
</google-map-marker>
</google-map>
<iron-ajax
id="getMarkers"
url="http://localhost:9001/vehicle-markers"
handle-as="json"
on-response="updateMarkers">
</iron-ajax>
</template>
<script>
class MyApplication extends Polymer.Element {
static get is() { return 'ra-app'; }
static get properties() {
return {
prop1: {
type: String,
value: 'ra-app'
},
lat1: {
type: Number,
value: 37.79
},
count:{
type: Number,
value: 1
},
marker_data: {
type: Array,
}
};
}
ready(){
super.ready();
var self = this;
self.$.getMarkers.generateRequest();
setInterval(function(){
// debug
console.log('my interval callback' + self.lat1);
self.lat1 = 37.79 + .01 * (self.count % 5);
self.count += 1
self.$.getMarkers.generateRequest();
}, 1000)
}
updateMarkers(data){
this.marker_data = data.detail.response;
console.log(this.marker_data)
var i = 0;
var len = this.marker_data.length;
for (; i < len;i++ ) {
// Eliminate null values in recent_positions array
this.marker_data[i].recent_positions = this.marker_data[i].recent_positions.filter(Boolean);
console.log('In updateMarkers, data from server:' + this.marker_data[i].current_lat + ' ' +
this.marker_data[i].current_lon);
console.log('Google maps version: ' + google.maps.version)
}
}
}
window.customElements.define(MyApplication.is, MyApplication);
</script>
</dom-module>
Have you tried to use array mutation methods.. Polymer isn't noticed about changes in arrays, so you have to call notifyPath or just use array mutation methods . Which means in your case that you should use this.set method

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 sending/receiving events among sibling elements

Assume I have two sibling elements, and <element-b> fires an event. How does <element-a> listen to the event without having to add imperative code to the parent?
<dom-module id="parent-element">
<element-a></element-a>
<element-b></element-b>
</dom-module>
where <element-a> and <element-b> are:
<dom-module id="element-a">
<template>
<style include="shared-styles">
</style>
</template>
<script>
Polymer({
is: 'element-a',
listeners: {
'element-b': 'handleEvent',
},
ready: function() {
console.log('fired from element a')
this.fire('element-a', {employee: ''});
},
handleEvent: function (e) {
console.log('received element b event', e)
}
});
</script>
</dom-module>
<dom-module id="element-b">
<template>
<style include="shared-styles">
</style>
</template>
<script>
Polymer({
is: 'element-b',
listeners: {
'element-a': 'handleEvent',
},
ready: function() {
console.log('fired from element b')
this.fire('element-b', {employee: ''});
},
handleEvent: function (e) {
console.log('received element a event', e)
}
});
</script>
Thanks!
You could use <iron-signals> for that.
Add an <iron-signals> listener in one element:
// element-b
<iron-signals on-iron-signal-element-a="_onSignalElementA"></iron-signals>
_onSignalElementA: function(e) {
const newDate = e.detail;
...
}
...and fire an iron-signal event (with data) in the other:
// element-a
this.fire('iron-signal', {name: 'element-a', data: new Date()});
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo'
});
Polymer({
is: 'element-a',
_onClick: function() {
this.fire('iron-signal', {name: 'element-a', data: new Date()});
}
});
Polymer({
is: 'element-b',
_onSignalElementA: function(e) {
this._message = `b received: ${e.detail}`;
}
});
});
<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">
<link rel="import" href="iron-signals/iron-signals.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<element-a></element-a>
<element-b></element-b>
</template>
</dom-module>
<dom-module id="element-a">
<template>
<button on-tap="_onClick">Fire event</button>
</template>
</dom-module>
<dom-module id="element-b">
<template>
<iron-signals on-iron-signal-element-a="_onSignalElementA"></iron-signals>
<div>[[_message]]</div>
</template>
</dom-module>
</body>
codepen

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');
}