Polymer paper tabs not working - polymer

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

Related

is it possible nest/inner dom-if where the second dom-if depends on value oberseved from the first dom-if block

I read carefully these threads
Polymer 1 nested dom-if within dom-repeat not updating when data changes
how to dynamically append an element to dom-if in Polymer?
How to access content of dom-if inside a custom element?
that may have some relation with my question but I didn't manage find any clue if I can do what I want and how.
In my company, there are several flows, each one for each business flow and each step of the flow is a screen coded as a Polymer 1 web component. All them are warraped in a root Polymer component which defines the route.
A simple exemple would be:
my-root-component:
<dom-module id="my-root-component">
<template>
<first-obrigatiory-page which-route={aValueReturnedFromFirstComponent}></first-obrigatiory-page>
<template is="dom-if" if="[[_isTrueFunction(aValueReturnedFromFirstComponent)]]" restamp>
<second-page which-sub-route={aValueReturnedFromSecondComponent}></second-page>
<template is="dom-if" if="[[_isTrueFunction(aValueReturnedFromSecondComponentComponent)]]" restamp>
<third-page ></third-page>
</template>
</template>
</template>
<script>
Polymer({
is: 'my-root-component',
behaviors: [doesntMatterHere],
properties: {
The first dom-if works as expected but the second seems not be taken in account and my third-page component is never showed.
I checked and the equivalent for _isTrueFunction(aValueReturnedFromSecondComponentComponent) is returning true.
Does aValueReturnedFromFirstComponent really return anything, because you should declare the attribute as which-route="{{aValueReturnedFromFirstComponent}}" instead of using simple { }.
Does the whichRoute (note the camelCase) property in the first-obrigatiory-page element have the notify: true property so the variable actually sends back the updated value?
I usually set observers on variables whenever dom-ifs don't update so I can see if they really change or not, and then set the variables myself through the console with document.querySelector('my-root-component').set('aValueReturnedFromFirstComponent', true) so I can see that the dom-if really updates.
A workaround could be to use events, but what you've done should work.

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.

Issue with two-way binding inside dom-repeat in Polymer 1.0

I have a simple template like this
<template is="dom-repeat" items="[[items]]">
<paper-button active="{{item.selected}}" toggles raised>
<span>[[item.selected]]</span>
</paper-button>
</template>
If I activate the first paper-button in the list by tapping it and then call
this.set('items.0.selected', !this.items[0].selected);
It gets deactivated.
But then if I try the exact steps above again, the button doesn't get deactivated, which makes the button state and the selected value out of sync.
Why is it doing this? The issue can be replicated over here.
Interesting question. So I tried to use a single paper-button binding to a single item instance and it turned out to be working fine, which got me thinking that it might have something to do with path binding inside an array.
So I then added a tap handler to the paper-button and every time it's tapped, do a notifyPath on the selected subproperty path with the value of itself -
this.notifyPath('items.0.selected', this.items[0].selected);
And it works.

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.

How to bind HTML5 datalist to paper-input?

I need to bind a datalist to a paper-input element, something like we have here HTML5 DataList Example. It does not work as the example shows, can someone please help. Thank you.
From your question, I don't believe a paper-input is what you are looking for. If you look at the documentation at The Polymer Project it describes the paper-input as "paper-input is a single-line text field for user input".
What you might be looking for is the paper-dropdown-menu (<-- look at ths link) with a core-menu as the element you are going to bind your data to.
I included a skeleton of how you would bind your data. Remember that you still need to add all the references to the Polymer elements, and polyfills.
<template is="auto-binding">
<!-- other content -->
<paper-dropdown-menu>
<paper-dropdown class="dropdown colored">
<core-menu class="menu">
<template repeat="{{countries}}">
<paper-item>{{}}</paper-item>
</template>
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
</template>
<script>
scope = document.querySelector('template[is=auto-binding]');
scope.countries= [
'Mexico',
'United States',
'Canada'
];
</script>
As recommended by this reply, you could wrap paper-input-decorator with input and datalist inside.
You would have the same result as with paper-input but more explicit and therefore more customizable.