How to changeURL via data of app-route element - polymer

Is it possible to change the URL via changing the app-route data object in polymer? Like described here: https://www.polymer-project.org/1.0/toolbox/routing#change-routes
In this example they are using this.set('routeData.user', 'mary'); to change the URL.
In our case its not working and we cant find the problem in our code.
We nearly removed all our code and just using this app-router configuration:
<app-route route="{{route}}"
pattern="/:view"
data="{{routeData}}">
</app-route>
In our attached lifecycle event we are using this:
attached: function(){
var self = this;
setTimeout(function(){
self.set('routeData.view', 'GNAAA');
});
}
Expected URL in address bar is
http://localhost:8888/polymer/index.html#/GNAAA
But we only got
http://localhost:8888/polymer/index.html#/
What are we missing here. Why we cant set the URL via the data object as mentioned in the docs? Maybe its a bug? But we cant find something on the GutHub Buglist of app-route.
UPDATE: We are also using iron-location to get query params from URL. If we remove iron-location all works as expected. So we currently created an issue on github.

Try adding <app-location route="{{route}}"></app-location> before your <app-route> statement.
Or, if you prefer to use iron-location, use iron-route-converter:
<iron-location path="{{path}}" query="{{query}}"></iron-location>
<iron-query-params
params-string="{{query}}"
params-object="{{queryParams}}">
</iron-query-params>
<app-route-converter
path="{{path}}"
query-params="{{queryParams}}"
route="{{route}}">
</app-route-converter>
Also, don't forget to import all used components with <link rel="import"> tags or your components will not work, without telling you about it.

Related

Polymer 1.x: iron-data-table does not load data nor header styles on first render when inside neon-animated-pages

The below screenshot shows how my iron-data-table element looks when it first loads. Notice the data is missing and the headers are not fully formatted (the width seems to be too small to show the column header labels).
However, if I enter a character in the filter fields or click one of the sort buttons, the iron-data-table seems to re-draw itself and it looks fine. The columns and headers render properly and the data populates the table as expected.
This problem started when I added some directories to my file structure nested my iron-data-table inside neon-animated-pages. I double checked and all my imports are loading correctly. But I suspect that, somehow, there is a slight delay in fetching the data and somehow the table might be trying to render before the data arrives and not refreshing after the data arrives.
So I tried to add the following function. But to no avail. There is no render() method for iron-data-table.
<iron-data-table id="grid" ...
....
attached: function() {
this.async(function() {
this.$$('#grid').render();
}.bind(this), 500);
},
What could be causing this behavior? And what should I try next?
Edit
This plunk demonstrates the desired iron-data-table behavior.
This plunk demonstrates my problem behavior. (Not finished yet. Currently in progress.)
The configuration is approximately as follows.
parent-el.html
<neon-animated-pages>
...
<container-el...>...</container-el>
</neon-animated-pages>
container-el.html
<child-el ...>...</child-el>
child-el.html
<iron-data-table ...></iron-data-table>
Edit 2
Based on #SauliTähkäpää's comment, I tried the following fix unsuccessfully.
parent-el.html
<neon-animated-pages id="animator" ...>
...
<container-el...>...</container-el>
</neon-animated-pages>
...
attached: function() {
this.async(function() {
this.$.animator.notifyResize();
}.bind(this), 50);
},
Not that familiar with neon-animated-pages but by looking at the docs, it should call notifyResize() on selected pages as long as they extend iron-resizable-behavior.
So I think your options are either to make sure <container-element> and other elements in the tree are extending iron-resizable-behavior OR override the resizerShouldNotify to notify the grid directly. See more here: https://elements.polymer-project.org/elements/neon-animation?active=neon-animated-pages#method-resizerShouldNotify
To explicate for anyone who follows this question later...
Per #SauliTähkäpää's accepted answer, I successfully added the following code to each element in the chain (i.e., beginning with the element containing neon-animated-pages and ending with the element containing iron-data-table — in this example, that would be parent-el, container-el, and child-el).
parent-el.html, container-el.html, child-el.html.
<link rel="import" href="path/to/bower_components/iron-resizable-behavior/iron-resizable-behavior.html">
...
behaviors: [
Polymer.IronResizableBehavior,
],

Polymer 1.0: more-route selectedParams params not set

I am wondering if selectedParams is supported for Polymer 1.0.
I am following the doc of more-route
https://github.com/PolymerLabs/more-routing
in the README file.
<link rel="import" href="../bower_components/more-routing/more-routing.html">
<more-routing-config driver="hash"></more-routing-config>
<more-route name="login" path="/">
</more-route>
<more-route name="inbox" path="/inbox">
<more-route name="viewemail" path="/:threadId">
</more-route>
</more-route>
<more-route-selector selectedParams="{{params}}" on-click="bodyClick">
<iron-pages selected="{{route}}" class="fullbleed fit">
<section route="login" >
</section>
<section route="viewemail" class="layout vertical fit">
Test params : <span>{{params}}</span> End
Test params : <span>{{params.threadId}}</span> End
<span>{{route}}</span>
</section>
</iron-pages>
</more-route-selector>
The problem is that params is not set, so I cannot reference the threadId param in the path.
The routing it working which means for /inbox/testid is routed to section with route="viewemail", but params is not set.
selectedParams should be written as selected-params. From 1.0 docs:
Attribute names with dashes are converted to camelCase property names by capitalizing the character following each dash, then removing the dashes. For example, the attribute first-name maps to firstName.
So your more-route-selector should be declared as follows:
<more-route-selector selected-params="{{params}}" on-click="bodyClick">
<more-route name="viewemail" path="/:threadId">
above in "routes.html" binds name to the threadId you want a ref to ....
When you use those in template, get a context...
<more-route context name="viewemail" params="{{params}}"></more-route>
... so you can make use of those properties within the Polymer class...
ready: function() {
if (typeof this.params.viewemail != 'undefined'){
this._mvar = this.params.viewemail;
this.$.get_divID = _mvar;
if(MoreRouting.getRoute('viewemail').active){...}
}
},
As you already pointed out in this Github issue, the behavior is a bug of the Polymer 1.0 migration of more-routing (call it missing feature, as there is simply no instruction that would set the selectedParams).
As long as no fix exists, you have two options to circumvent the problem manually without modifying the project source code:
1. Workaround: Listen on on-more-route-change on the more-route-selector element.
The current routing params can be accessed as event.detail.newRoute.params from the event handler (caution: that object is not serializable due to non-enumerable JS getters). Manually hand over these params to your elements.
2. Good solution: Use context-aware routes.
selectedParams are not set on the more-route-selector, but well on routes. Include a context route to your pages and bind {{params}} on them.
Therefore, you may create a named route in your router file as:
<more-route path='/path/:param' name='path-route'/>
Reference this route by name from within your page element (or state the path directly):
<more-route context name='path-route' params='{{params}}'/>
Place the page element in more-router-selector as before. Parameters are bound to {{params}}.
The pattern is explained on the project page and in use in the demo app.

Call Method of Child Web Component

I'm really having difficulty trying to figure out how to call a function of a nested Polymer web component.
Here's the markup:
<rise-playlist>
<rise-playlist-item duration="5">
<rise-distribution distribution='[{"id":"VGZUDDWYAZHY"}]'></rise-distribution>
</rise-playlist-item>
</rise-playlist>
The rise-distribution component has a canPlay function that I would like to call from inside of rise-playlist.
The dom-module definition of rise-playlist looks like this:
<dom-module id="rise-playlist">
<template>
<content id="items" select="rise-playlist-item"></content>
</template>
</dom-module>
I can successfully access the rise-distribution element like this:
var distribution = Polymer.dom(this.$.items[0]).querySelector("rise-distribution");
However, when I try to call distribution.canPlay(), it says that distribution.canPlay is not a function.
I've defined the dom-module of rise-playlist-item like this:
<dom-module id="rise-playlist-item">
<content id="dist" select="rise-distribution"></content>
</dom-module>
Not sure if I need that <content> tag, although neither works.
Any ideas?
Thx.
I know that there have been a while but I am sure this problems still occurs as it is being viewed number of times.
Probably there is a problem with your component definition. Let me explain.
This is the way you put your child component inside DOM:
<your-child-component></your-child-component>
And and this should be the definition of your component:
Polymer({
is: 'your-child-component',
apiMethod: function() {
//some stuff
}
});
If you by mistake or due copy-paste error mistype the is: 'your-child-component' part, so it will not reflect the <your-child-component> you will get confused becouse your:
this.$$('your-child-component').apiMethod();
will tell you that there is no method you are willing to call.
Polymer correctly identified and selected from DOM <your-child-component> but if you have different is property (like for example is: your_child_component>) it will not attach its API to dom element you selected.
I hope that it will help if anyone ever will encounter this problem.

How to create an instance of Polymer element programmatically?

Please refer to this JSBin, basically I would like to create an instance of an element in its parent element scope. Wondering how should I do this?
If possible, is there a declarative way to do this?
Thanks.
PS. Please open the link in Chrome only.
There are several ways to instantiate and element.
Declarative:
<my-element>
JS:
document.createElement('my-element');
Constructor (if one is find):
new MyElement();
See http://www.html5rocks.com/en/tutorials/webcomponents/customelements/#instantiating
I believe you are looking for the constructor (see here) attribute.
You need to include it in your polymer element declaration.
<polymer-element name="p-paper"
attributes="content"
constructor="Paper"
noscript>
And then you can create instances of your element like this -
// How to create an instance of <p-paper> here?
var paper = new Paper();

How to include a CSS link if a call isn't done via AJAX?

I have a page 'foo.html' that populates a table via AJAX 'ajax.html?options=option1'(accesses a database.)
'foo.html' has a css linked to it that makes the table from ajax.html look nice. However, I'd like to have ajax.html also look nice with a css if it is directly accessed. if I add <link rel="stylesheet" type="text/css" href="/dev/css/default.css" /> then the AJAX inserts the link again in foo.html which I don't want. Is there any way I can make the css link code not show up in the AJAX call or only show up on non-AJAX calls?
Thanks.
an easy way i can think of to solve this problem is to pass an additional parameter that defines the calling context.
The easiest way to do this is to use jQuery.
Load the ajax.html page with jQuery.get()
on success, do :
Remove the stylesheet : $('link[rel=stylesheet]').remove();
If you then want to add another stylesheet :
var link = $("<link>");
link.attr({
type: 'text/css',
rel: 'stylesheet',
href: 'http://domain.com/stylesheet.css'
});
$("head").append( link );
Or change it later :
$("link").attr("href","http://domain.com/stylesheet.css");