Polymer App Routing not picking up variables - polymer

I'm trying to pass variables in my urls using App Location and App Routing in Polymer, but the subroute doesn't seem to be picking up the variables. Can anyone help me figure out what I'm doing wrong?
Code:
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/desk/:project/:scene"
data="{{data}}"
tail="{{subroute}}">
</app-route>
The route.path is showing up as /variable/variable, but the project and scene are blank.
Any help would be appreciated.

The code below use two elements to monitor the complete URL.
The first will bind to the project value and output a {{subroute}} for the second element.
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/desk/:project"
data="{{data}}"
tail="{{subroute}}">
</app-route>
The second will bind to the scene value.
<app-route
route="{{subroute}}"
pattern=":scene"
data="{{data}}">
</app-route>

The values of project and scene are read from data, which is bound to <app-route>.data (as in data.project and data.scene).
So, if your URL were http://localhost:8080/desk/123/456, your data object would contain:
{
project: '123',
scene: '456'
}
codepen

Related

Polymer paper tabs not working

I have two separate ways of setting up tabs in my application one works and one doesn't. Not sure what I am doing wrong. Both examples are inside a custom element template
This way works:
<paper-tabs id="clinic-tabs" selected="{{clinicId}}" attr-for-selected="cid" scrollable>
<template is="dom-repeat" items="[[clinics]]" filter="_shouldDisplay" observe="active use">
<paper-tab cid="[[item.id]]">[[item.name]]</paper-tab>
</template>
</paper-tabs>
This way doesn't
<paper-tabs selected="{{page}}" attr-for-selected="page" scrollable>
<paper-tab page="details">Patient Details</paper-tab>
<paper-tab page="finance">Finance Records</paper-tab>
<paper-tab page="history">Patient History</paper-tab>
<paper-tab page="preopp1">Pre Op Assessment</paper-tab>
<paper-tab page="surgery">Surgery Settings</paper-tab>
<paper-tab page="postop">Post Op Assessment</paper-tab>
</paper-tabs>
If I put a breakpoint on the onTap function in paper-tab.html, on the first one if I use console to output a value
this.cid prints the correct value. If I put a breakpoint on the second version then this.page is undefined, although this.getAttibute('page') does return the correct value. As a result in the second version there is no change to the {{page}} value and so my tabs don't do anything.
Anyone any idea how I can setup the markup on the second one so I can use the page property in my custom element to action things (actually switching between different pages using <iron-pages>)
I actually found out that the problem is the page property in the host element (declared inside a behavior) is readOnly for the second case.
paper-tabs does not have attr-for-selected. it works on numeric selecting. so selected = 0, selected = 1 and so on. the first one example works only because you are propably setting IDs from 0 to x.
documentation: https://www.webcomponents.org/element/PolymerElements/paper-tabs/elements/paper-tabs

How to changeURL via data of app-route element

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.

Can you dynamically create a binding property name in Polymer?

In Polymer I am creating some <app-route> elements in a <dom-repeat> as follows:
<template is="dom-repeat" items="{{myItems}}">
<app-route route="[[_route]]"
pattern="/view-{{index}}/:data"
data="{{_routeData}}"
active="{{_routeActive}}">
</app-route>
</template>
I'd like to use {{index}} within the data and active attribute values to create a dynamic binding property name such as {{_route{{index}}Data}} i.e evaluating {{index}} when creating the binding name. This would mean that they are unique for each route.
Is it possible to do this in Polymer? If not are there any alternative approaches?

Polymer route/iron-pages not working?

I am just trying out Polymer 1.0. I find that app-route/iron-pages is not working. Navigating between routes does not appear to show the correct view. Not sure which part went wrong:
In the main file:
<app-drawer-layout>
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/:view"
data="{{routeData}}"
tail="{{subroute}}"></app-route>
<app-drawer>
<main-drawer></main-drawer>
</app-drawer>
<app-header-layout>
<app-header>
<paper-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<div class="title">
Expenses App
</div>
</paper-toolbar>
<iron-pages selected="[[view]]">
<expenses-dashboard name="dashboard" route="{{subroute}}"></expenses-dashboard>
<expenses-settings name="settings" route="{{subroute}}"></expenses-settings>
</iron-pages>
</app-header>
</app-header-layout>
</app-drawer-layout>
In side both expenses-dashboard and expenses-settings is just placeholder content like:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module id="expenses-dashboard">
<template>
<h1>Dashboard</h1>
</template>
<script>
Polymer({
is: 'expenses-dashboard'
});
</script>
</dom-module>
For <iron-pages selected="[[view]]">, should I be using routeData.view or view? I tried both didnt seem to change anything.
The code on GitHub
There are a few issues in your code...
Since your <iron-pages>.selected property is bound to an undefined property ("view"), <iron-pages> does not change its page. In your <app-route> data binding, the route parts are parsed into routeData, where the :view slug would be accessed with routeData.view, which is what you should be binding to <iron-pages>.selected:
<iron-pages selected="[[routeData.view]]">
The default selector for <iron-pages> is the page index (i.e., the child index of its contents), so selected would normally have to be an integer between 0 and N - 1 inclusively, where N is the number of child pages. But you could change that. It looks like you want the route to specify the page, which would need to match the name of a page under <iron-pages>. To use "name" as the selected attribute, you'd have to configure <iron-pages>.attrForSelected property:
<iron-pages selected="foo" attr-for-selected="name">
<div name="foo"></div>
<div name="bar"></div>
</iron-pages>
It might also be a good idea to specify a fallback selection, since the user could accidentally navigate to a URL that doesn't correspond to an existing page (e.g., https://mypage.com/#/non-existent-page).
<iron-pages selected="[[routeData.view]]" attr-for-selected="name" fallback-selection="foo">
<div name="foo"></div>
<div name="bar"></div>
</iron-pages>
In <main-drawer>, you may want to define menuTap() with ES5 syntax (instead of ES6) for maximum browser compatibility.
Polymer({
// menuTap(e) { ... } // <-- ES6
menuTap: function(e) { ... }
});
Your menuTap() function sets the window.location to a raw path, which noticeably refreshes the page. You could avoid the page refresh by using hash paths, where the intended sub-path of the URL is prefixed with a # (e.g., https://mypage.com/#/settings).
For hash paths, configure <app-location> to ignore the hash prefix by setting the useHashAsPath property:
<app-location use-hash-as-path route="{{route}}">
If you prefer to avoid hash paths, you could follow Polymer CLI's app-drawer-template, which uses anchor tags inside an <iron-selector> to set the location, which <app-location> detects and updates its route accordingly. Or you could pass the route in from <expenses-app> and then use this.set('route.path', "dashboard") inside of menuTap().
With the changes above, the following would occur when the user navigates to https://mypage.com/#/dashboard.
<app-location> would set the route property to /dashboard.
<app-route> would parse the route and set routeData.view to dashboard.
<iron-pages> sees routeData.view as dashboard, which matches the specified attribute on a child, which in turn causes only that page to be displayed.
For reference, the guide on Encapsulated Routing with Elements is quite useful.

Polymer elements: to nest or not to nest?

We're developing a data visualization library using Polymer, and I must say I'm impressed with what Polymer lets you do. We do have a question, though...
First: here's an example snippet of code showing a data visualization:
<template is="auto-binding">
<our-loaddata url="data/data.csv" data="{{data}}"></our-loaddata>
<our-scatterplot data="{{data}}"></our-scatterplot>
<our-barchart data="{{data}}" dimension="weight"></our-barchart>
<our-histogram data="{{data}}" dimension="weight" binSize=10></our-histogram>
</template>
The our-loaddata loads the dataset from a file data/data.csv, performs some transformations (e.g. converting strings to numbers, calculating distributions, ...) and makes it available through {{data}} to the our-scatterplot, our-barchart and our-histogram. However, I'm not completely satisfied with the setup. Conceptually, the our-loaddata is different from the other three, and should precede them. As an alternative, we have also tried the following (renaming loaddata to app and nesting all visuals within the app):
<template is="auto-binding">
<our-app url="data/data.csv" data="{{data}}">
<our-scatterplot data="{{data}}"></our-scatterplot>
<our-barchart data="{{data}}" dimension="weight"></our-barchart>
<our-histogram data="{{data}}" dimension="weight" binSize=10></our-histogram>
</our-app>
</template>
Although this also works, we noticed that it doesn't matter if we close the </our-app> element before or after all the visual elements.
What would be the most canonical way to handle this in Polymer? What is the difference between the approaches that I showed here?
you could use the conditional template to check if data is present and then send the other elements to the dom if true or show a loader if false. (careful getting to used to this i don't think it is currently in 0.8. sad IMO i <3 it)
<template is="auto-binding">
<our-loaddata url="data/data.csv" data="{{data}}"></our-loaddata>
<template if="{{data}}">
<our-scatterplot data="{{data}}"></our-scatterplot>
<our-barchart data="{{data}}" dimension="weight"></our-barchart>
<our-histogram data="{{data}}" dimension="weight" binSize=10></our-histogram>
</template>
<template if="{{!data}}">
<pretty-loadingscreen></pretty-loadingscreen>
</template>
</template>
the would give you seperation of elements you were looking for.