app-location deletes query string parameters - polymer

I have a very simple polymer 2 app, which uses query query string parameters. Moving to Polymer 2.0.1 and app-location 2.0 (instead of rc and preview versions), I noticed that simply having an app-location element deletes all query string parameters from the url.
Try this url: https://api-1913.s3-eu-west-1.amazonaws.com/index.html?foo=bar, and notice how the query string is removed during loading.
Here's all the code:
index.html:
<!DOCTYPE HTML>
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="/my-app.html">
<html>
<head>
</head>
<body>
<my-app></my-app>
</body>
</html>
my-app.html:
<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/app-route/app-location.html">
<dom-module id="my-app">
<template>
<app-location></app-location>
<h1>Coin</h1>
</template>
<script>
class App extends Polymer.Element{
static get is(){return 'my-app'}
ready(){
super.ready()
console.log('ready')
}
}
customElements.define(App.is, App)
</script>
</dom-module>
Specifying query-params attribute to map it to a property of App does not change anything. Remove the app-location element and query string is kept.
Has anyone seen this behavior? Is there any workaround - except a rollback to a previous version?

It is a bug. You can temporarly remove the default value in iron-location element until the fix is released.
Lines to remove
value: function() {
return {};
}
Affected property
paramsObject: {
type: Object,
notify: true,
value: function() {
return {};
}
},
Reference:
https://github.com/PolymerElements/iron-location/pull/86/commits/3732e93ce2197178f76c3c2073438b9cd15096b4

Related

Polymer 2.0 - How do I use iron-ajax?

I am trying to bind local properties.json and trying to create dynamic elements, but the problem is I am not getting any console errors and not seeing JSON in the UI.
I didn't find a Polymer 2.0 example for using <iron-ajax>, but I found ones for Polymer 1.0 only.
Here's the code I've tried:
polymer-input.html
<link rel="import" href="https://www.polymer-project.org/0.5/components/polymer/polymer-element.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/iron-ajax/iron-ajax.html">
<dom-module id="polymer-app">
<template>
<style>
:host {
display: block;
}
</style>
<iron-ajax auto="" url="properties.json" handle-as="json" last-response="{{ajaxResponse}}"></iron-ajax>
<template is="dom-repeat" items="[[ajaxResponse]]">
<span>[[item.name]]</span>
</template>
<h2>Hello [[prop1]]!..[[ajaxResponse]]</h2>
</template>
<script>
/**
* #customElement
* #polymer
*/
class PolymerApp extends Polymer.Element {
static get is() { return 'polymer-app'; }
static get properties() {
return {
prop1: {
type: String,
value: 'polymer-app'
}
};
}
}
window.customElements.define(PolymerApp.is, PolymerApp);
</script>
</dom-module>
index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<title>polymer</title>
<meta name="description" content="custom ele">
<script src="https://www.polymer-project.org/0.5/components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="polymer-app/polymer-app.html">
<link rel="import" href="polymer-input/polymer-input.html">
</head>
<body>
<polymer-app></polymer-app>
</body>
</html>
properties.json:
{
{
name:"Name",
type:"string",
size:20
},
{
name:"Age",
type:"number",
size:20
}
}
I am getting below output instead of properties json data
The first problem is your demo uses a base URL for Polymer 0.5, while your code is using Polymer 2.0 syntax.
That is, this code:
<link rel="import" href="https://www.polymer-project.org/0.5/components/polymer/polymer-element.html">
<link rel="import" href="https://www.polymer-project.org/0.5/components/iron-ajax/iron-ajax.html">
...should be something like this:
<link rel="import" href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/polymer/polymer-element.html">
<link rel="import" href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/iron-ajax/iron-ajax.html">
Second, your properties.json file contains invalid JSON. It looks like you meant to use square brackets for array data; and your keys are missing quotes. You'll notice that running the file contents through JSON.parse() would throw an error.
This text:
{
{
name:"Name",
type:"string",
size:20
},
{
name:"Age",
type:"number",
size:20
}
}
...should be something like this:
[
{
"name":"Name",
"type":"string",
"size":20
},
{
"name":"Age",
"type":"number",
"size":20
}
]
Third, note that <iron-ajax> automatically sets <iron-ajax>.lastResponse to null if <iron-ajax>.handleAs is json and the response cannot be parsed as JSON. In your case, the invalid JSON in properties.json would cause lastResponse to be set to null, preventing your example from rendering the intended fields.
Here's a working Polymer 2 <iron-ajax> demo (using your example code) with all corrections made:
http://plnkr.co/edit/2mpJd1b0UF5FqAr2BOxL?p=preview

How to implement custom filters in Polymer 1.7.x

I am trying to implement a custom filter using Polymer v1.7.0 currently. However, it does not work at all; when I try to use a filter the output is just the raw expression, unprocessed.
I have tried it like it's done here: https://github.com/PolymerLabs/polymer-patterns/blob/master/snippets/filters/using-custom-filters.html but using this code:
<div id="toFixed">{{10.123456789 | toFixed(2)}}</div>
only results in
{{10.123456789 | toFixed(2)}} in the resulting document.
Is my linked source outdated? I couldn't find any valuable information in the Polymer docs so a nudge into the right the direction is appreciated.
You don't need pipe in Polymer 1.x to achieve this. You can directly call an function and pass it the value that you want to
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<dom-module id="my-element">
<template>
{{format(myVal)}}
<br>{{format("hello")}}
</template>
</dom-module>
<script>
Polymer({
is: "my-element",
properties: {
myVal: {
type: String,
value: "Hi"
}
},
format: function(input) {
return input + " John";
}
});
</script>
<my-element></my-element>

Polymer: Whats the difference between computed property and function like {{some(prop1)}}

Whats the difference between defining a computed property and using it like {{prop}}
prop: {
type: String,
computed: 'some(prop1)'
}
vs a function binding like
{{some(prop1)}}
The property is, as the name implies, also a property of the node object. It can notify outside listeners or reflect to attribute.
Function binding is only used to that. You can call it from the outside but it should have no effect - assuming that the function has no side-effects which is shouldn't.
The most important difference however, is that compute function will evaluate for each binding usage. Computed property will evaluate only once when a dependency changes. See below what happens in the console whenever you click INCREMENT.
Polymer({
is: 'my-elem',
properties: {
i: {
type: Number,
value: 0
},
c: {
computed: 'compute(i)'
}
},
inc: function() {
console.clear();
this.i += 1;
},
compute: function(i) {
console.log('computing property binding');
return i * 2;
},
f: function(i) {
console.log('computing function binding');
return i * 2;
}
});
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import"/>
<link href="paper-button/paper-button.html" rel="import" />
</head>
<body>
<my-elem></my-elem>
<dom-module id="my-elem">
<template>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<paper-button on-tap="inc">Increment</paper-button>
</template>
</dom-module>
</body>
</html>

Issue with data binding in Polymer templates

I have a page where I am binding an array to input fields. Data binding seems to be working somewhat strange.
Please have a look at below example
<!doctype html>
<html>
<head>
<script src='bower_components/webcomponentsjs/webcomponents-lite.js'></script>
<link rel='import' href='bower_components/polymer/polymer.html'>
<link rel='import' href='bower_components/paper-input/paper-input.html'>
</head>
<body unresolved>
<dom-module id='base-page'>
<template>
<template is='dom-repeat' as='cell' items='{{data}}'>
<paper-input value='{{cell}}'></paper-input>
</template>
</template>
</dom-module>
<script>
Polymer({
is: 'base-page',
properties: {
data: {
type: Array,
value: function() {
return [0,0]
}
}
}
});
</script>
<base-page></base-page>
</body>
If I edit the content in the second paper-input, data is changed in both. If I however initialize my data array to e.g. [0, 1], then the cells apparently looks different to start with and therefore it is able to differentiate between the cells and data binding seems to work. Whats the issue?, but more importantly, how can I make it work?
Cheers and thanks :-)
AFAIK plain numbers don't work well in arrays. Especially here where Polymer can't tell them apart properly if they have the same value.
Wrap them in objects like
return [{value: 0}, {value: 0}]
and then use it like
<paper-input value='{{cell.value}}'></paper-input>

Polymer: how to parse the index to the elements using template repeat

I've been trying to use Polymer for a project I'm working on. And although I enjoyed it quite a lot so far, I ran into a problem I just can't solve.
I dumped it down to a simple example. Basically it's just a list element (item-list) that contains item elements (item-card) and i want to parse the items position to the element via the attribute pos. But for some reason the items attribute is allways undefined! Is this because the attribute is bound to the variable i, which dies after the template repeat? If so, how do I work around it? Is there a different approach I should be using here?
SOLUTION: You can find the solution by reading through all the comments, but to sum it up: apperantly there was a timing issue and the attribute wasn't ready at the ready callback. But I found out about the domReady callback (polymer lifecycle documentation). Using domReady it works just fine! Thanks to Günter Zöchbauer for the help!
This is the item-list.html:
<link rel="import" href="components/polymer/polymer.html">
<link rel="import" href="item-card.html">
<polymer-element name="item-list">
<template>
<style>
</style>
<template repeat="{{values, i in data.data}}">
<item-card pos="{{i}}"></item-card>
</template>
</template>
<script>
Polymer({
created: function()
{
this.num = 123456;
this.data = { "data":
[
{
"value":999
},
{
"value":666
},
{
"value":555
},
{
"value":222
}
]
};
}
});
</script>
</polymer-element>
This is the item-card.html
<link rel="import" href="components/polymer/polymer.html">
<polymer-element name="item-card" attributes="pos">
<template>
<style>
</style>
</template>
<script>
Polymer({
ready: function()
{
console.log("ready: " + this.pos);
}
});
</script>
</polymer-element>
I didn't bother putting the index.html in, since it just containts one item-list element.
Thanks alot!!
I think you need a pos field in <item-card> in addition to the attributes="pos" declaration.
The repeated element also references the bound model which can be accessed like querySelector('item-card').templateInstance.model property.
See https://github.com/PolymerLabs/polymer-selector/blob/master/polymer-selector.html#L286 for an example.
Info:
According to the comments it turned out to be a timing issue. The value wasn't yet assigned when the ready callback was called but using domReady worked.