Unable to change core-animated-pages with paper tabs - polymer

I'm trying to hook core-animated-pages with paper-tabs in my polymer appliaction. Everyghing looks cool , but I have trouble with changing core-animated-pages when I click on paper-tabs button
I'm trying to use This polymer tutorial , my version is very similar to tutorial so it should work. Unfortunately I can see only first core-page active or my URL is changing for http://myapp/#one or #two
My code below:
<template id="templ" is="auto-binding">
<div layout horizontal flex>
<paper-tabs id="tabs" valueattr="hash" selected="all" class="progress-tabs" self-end>
<template repeat="{{page in pages}}">
<paper-tab>{{page.name}}</paper-tab>
</template>
</paper-tabs>
</div>
<div layout horizontal center-center fit>
<core-animated-pages valueattr="hash" selected="{{hash}}"
transitions="slide-from-right">
<template repeat="{{page in pages}}">
<section hash="{{page.hash}}" layout vertical center-center>
<div>{{page.name}}</div>
</section>
</template>
</core-animated-pages>
</div>
</template>
And script:
<script>
Polymer('progress-page', {
ready: function () {
var template = this.shadowRoot.getElementById("templ");
template.pages = [
{name: 'Single', hash: 'one'},
{name: 'page', hash: 'two'}
];
}}
);
</script>

In the paper-tabs use 'selected' attribute to get the 'hash' value of selected tab:
<paper-tabs id="tabs" valueattr="hash" selected="{{selected}}" class="progress-tabs" self-end>
Then us {{selected}} value to switch the core-pages:
<core-animated-pages valueattr="hash" selected="{{selected}}"
transitions="slide-from-right">
So, 'selected' attribute passes the value between tabs and pages.

Related

nesting elements and dynamic content inside dom-repeat - Polymer 1.0

I have a <parent> element, a <tabs> element inside it with an arbitrary number of tabs (purely for hiding/showing logic in the UI), and a <child> element inside each <tab>. Right now I have the following working:
<!-- inside parent.html: -->
<tabs></tabs>
<!-- inside tabs.html: -->
<template is="dom-repeat" items="{{tabs}}" as="tab" index-as="item_no">
<section>
<child id="element-{{tab.index}}"></child>
</section>
</template>
Only <parent> knows how many instances of <child> there needs to be (<tabs> merely receives an array from <parent> and iterates over it.
Is there a way to not hard-code <child> inside the local DOM of <tabs>? Thinking of using <content> and light DOM but no idea where to even start. Would it be a promising route to take?
Desired state:
<!-- inside parent.html: -->
<tabs>
// somehow specify base content to be rendered in each tab
</tabs>
<!-- inside tabs.html: -->
<template is="dom-repeat" items="{{tabs}}" as="tab" index-as="item_no">
<section>
// somehow inject stuff from parent element, perhaps via <content>?
</section>
</template>
This is my interpretation of your question, so I am not really sure if it will be OK with you. If I misunderstood you, please drop a comment and I will gladly update my answer.
I have come up with a simple element composition, requiring no dom-repeat or manual template stamping. The solution consists of two custom elements, namely my-parent and my-child.
The definitions for both custom elements are the following:
<dom-module id="my-parent">
<template>
<tabs>
<content></content>
</tabs>
</template>
<script>
Polymer({
is: 'my-parent',
});
</script>
</dom-module>
<dom-module id="my-child">
<template>
<section>
<content></content>
</section>
</template>
<script>
Polymer({
is: 'my-child',
});
</script>
</dom-module>
And the proposed usage of them is the following:
<my-parent>
<my-child>First tab</my-child>
<my-child>Second tab</my-child>
<my-child>Third tab</my-child>
</my-parent>
Online demo: http://jsbin.com/hibuzafapu/1/edit?html,output
The resulting computed HTML code looks something like this:
<my-parent>
<tabs>
<my-child>
<section>
First tab
</section>
</my-child>
<my-child>
<section>
Second tab
</section>
</my-child>
<my-child>
<section>
Third tab
</section>
</my-child>
</tabs>
</my-parent>
If I understood you correctly, then only the <my-child> tag wrapping the <section> tag is redundant. Currently the aforementioned tag does nothing and is just a block-level element that wraps everything (just like a div). If this bothers you, then you can actually omit the <section> tag and put all the styling directly on the <my-child> tag.
In this case, the resulting computed HTML would look something like this:
<my-parent>
<tabs>
<my-child>
First tab
</my-child>
<my-child>
Second tab
</my-child>
<my-child>
Third tab
</my-child>
</tabs>
</my-parent>
UPDATE
In order to add some dynamics to the solution (adding/removing tabs), you have two options: use dom-repeat and stamp the items in light DOM, or push the items array into the my-parent element and use dom-repeat there. Both options are very similar to implement and don't have much difference in the way they work.
Option A: stamping in light DOM:
Definitions for both custom elements remain unchanged, the only difference is how you use them. Instead of hardcoding the light DOM, you make it more dynamic.
<dom-module is="tmp-element">
<template>
<my-parent>
<template is="dom-repeat" items="[[myItems]]">
<my-child>[[item.content]]</my-child>
</template>
</my-parent>
</template>
<script>
Polymer({
is: 'tmp-element',
ready: function() {
this.myItems = [
{ content: "First tab" },
{ content: "Second tab" },
{ content: "Third tab" },
],
};
});
</script>
</dom-module>
<tmp-element></tmp-element>
The tmp-element is used purely to create a binding scope and to feed the data into the dom-repeat.
Live demo: http://jsbin.com/gafisuwege/1/edit?html,console,outputenter link description here
Option B: stamping inside parent:
In this option, the parent needs to have an additional property, in which will we will supply the array of items.
The new version of the my-parent element is the following:
<dom-module id="my-parent">
<template>
<tabs>
<template is="dom-repeat" items="[[items]]">
<my-child>[[item.content]]</my-child>
</template>
</tabs>
</template>
<script>
Polymer({
is: 'my-parent',
properties: {
items: Array,
},
});
</script>
</dom-module>
And the usage is:
<dom-module is="tmp-element">
<template>
<my-parent items="[[myItems]]"></my-parent>
</template>
<script>
Polymer({
is: 'tmp-element',
ready: function() {
this.myItems = [
{ content: "First tab" },
{ content: "Second tab" },
{ content: "Third tab" },
];
},
});
</script>
</dom-module>
<tmp-element></tmp-element>
Here, I have also used a tmp-element (a different one than before) to feed the my-parent its' data.
Live demo: http://jsbin.com/kiwidaqeki/1/edit?html,console,output

how do i use multiple <content> tag in single polymer element?

I am trying to access same data in single element for two times, one for desktop navigation and one for responsive navigation(drawer toolbar). For this I use two content tags but it takes only one. In this this case what to do
<app-drawer-layout force-narrow>
<app-drawer id="drawer">
<app-toolbar></app-toolbar>
<!-- Nav on mobile: side nav menu -->
<paper-menu selected="{{selected}}" attr-for-selected="name">
<template is="dom-repeat" items="{{items}}">
<paper-item name="{{item}}">{{item}}</paper-item>
</template>
</paper-menu>
</app-drawer>
<app-header-layout>
<app-header class="main-header">
<app-toolbar>
<paper-icon-button class="menu-button" icon="menu" drawer-toggle hidden$="{{wideLayout}}"></paper-icon-button>
</app-toolbar>
<app-toolbar class="tabs-bar" hidden$="{{!wideLayout}}">
<!-- Nav on desktop: tabs -->
<paper-tabs selected="{{selected}}" attr-for-selected="name" bottom-item>
<template is="dom-repeat" items="{{items}}">
<paper-tab name="{{item}}">{{item}}</paper-tab>
</template>
</paper-tabs>
</app-toolbar>
</app-header>
</app-header-layout>
</app-drawer-layout>
<iron-media-query query="min-width: 600px" query-matches="{{wideLayout}}"></iron-media-query>
Polymer code:
Polymer({
is: 'x-app',
properties: {
selected: {
type: String,
value: 'Item One'
},
wideLayout: {
type: Boolean,
value: false,
observer: 'onLayoutChange',
},
items: {
type: Array,
value: function() {
return ['Item One', 'Item Two', 'Item Three', 'Item Four'];
}
}
},
onLayoutChange: function(wide) {
var drawer = this.$.drawer;
if (wide && drawer.opened) {
drawer.opened = false;
}
}
});
I have this type of code. What should I do to add menu element without using array. I want to add them separately from index at both app-header and app-drawer. but in index it should written one time as shown below.
<wt-header logo="logo url" enable-menu="true" enable-topbar="false">
<wt-menu>
<wt-tab name="TabName" action="http://example.com/action" />
<wt-tab name="TabName1" action="http://example.com/action2" />
<wt-tab name="TabName3" action="http://example.com/action3" />
</wt-menu>
</wt-header>
I think you need to provide it twice. <content> doesn't "produce" what you pass to an element, it just projects the content - <content> is just a slot where the passed content is shown.
If you want to provide it twice, then you need to add a select=".some" to at least one <content> to define what part of the projected content (the one that matches the selector .some) should be projected to this <content select=".some"> and what content should be projected to the other <content> element.
An alternative approach is to pass the content within a <template>...</template> and then use templatizer to append the content of the template multiple times. This is for example how <template is="dom-repeat"> or <iron-list> are doing it

app-indexeddb-mirror with Polymerfire

I built a simple page that has multiple tabs. Each tab loads a feed (collection/list) of articles from Firebase and renders cards on the page. Everything works as I wanted until I tried to persist the visited feeds into indexeddb with app-indexeddb-mirror.
Here's what I did:
<dom-module id="my-view1">
<template>
<style include="shared-styles">
</style>
<paper-tabs id="tabs"
attr-for-selected="value"
selected="{{selectedFeed}}"
scrollable>
<template is="dom-repeat"
items="[[feeds]]"
as="feed">
<paper-tab value="[[feed.key]]">[[feed.name]]</paper-tab>
</template>
</paper-tabs>
<firebase-query id="[[selectedFeed]]_feed"
app-name="myfirebaseapp"
path="/myfirebaseappdb/feed/[[selectedFeed]]"
data="{{articles}}">
</firebase-query>
<app-indexeddb-mirror
key="[[selectedFeed]]"
data="[[articles]]"
persisted-data="{{persistedArticles}}">
</app-indexeddb-mirror>
<template is="dom-repeat"
items="[[persistedArticles]]"
as="article">
<paper-card image="[[article.image]]" alt="image">
<div class="card-content">
<h1 class="card-text">[[article.title]]</h1>
<h4 class="card-text">[[article.abstract]]</h4>
</div>
</paper-card>
</template>
</template>
<script>
Polymer({
is: 'my-view1',
ready: function () {
this.feeds = [
{name: "Feed1", key: "feed1"},
{name: "Feed2", key: "feed2"},
{name: "Feed3", key: "feed3"},
{name: "Feed4", key: "feed4"}
];
}
});
</script>
What I want to do is cache each feed into indexeddb as an entry (feed name as key and the data as value), so they can be loaded when the app is offline. That's basically what app-indexeddb-mirror is for, right?
However I cannot get my head around the data flow between firebase-query and app-indexeddb-mirror, and I keep getting indexeddb entry overwritten/emptied when switching tabs.
Is there something I am not doing right? Thanks.
I solved this issue by swapping firebase-query and app-indexeddb-mirror.
I never knew sequence matters in Polymer, also this order is quite counter-intuitive.

set default tab/page selection

I'm building a simple app, with a few tabs and pages linked to them. I can get this to work fine, the problem is that there is no tab selected by default.
For example, I have a basic structure like this:
<paper-tabs attr-for-selected="data-route" selected="{{selected}}">
<paper-tab data-route="1">Tab 1</paper-tab>
<paper-tab data-route="2">Tab 2</paper-tab>
<paper-tab data-route="3">Tab 3</paper-tab>
</paper-tabs>
<iron-pages selected="{{selected}}">
<div data-route="1">Page 1</div>
<div data-route="2">Page 2</div>
<div data-route="3">Page 3</div>
</iron-pages>
Works fine. However when I open the page, none of the tabs are selected by default. If I wanted this done, I could assign 'selected' to equal a specific value, such as:
<paper-tabs attr-for-selected="data-route" selected="1">
<paper-tab data-route="1">TAB 1</paper-tab>
<paper-tab data-route="2">TAB 2</paper-tab>
<paper-tab data-route="3">TAB 3</paper-tab>
</paper-tabs>
The problem with this is that then the tab/page binding doesn't work.
So, simple question, how do I keep the binding while also setting a default tab?
Good Polymer programming wraps these elements in a custom element representing the app (or some subsection of the app). Adding a selected property in the properties section of the surrounding element with a default value will set the default tab [Warning: Still a Polymer newbie]. Perhaps add something like:
Polymer({
is: 'x-custom',
properties: {
selected: {
value: 1
}
}
});
Well, I think that ready function is the way to initialize !
ready: function() {
this.selected = 0;
}
Use the properties solution if you want "selected" to be used outside of your component

Polymer paper menu button

I am very new to web development and am attempting to learn to use polymer to create a simple webpage. I have created a drop down menu populated by the names in a json file similar to the below example. I cannot understand how to display the data associated with the selected menu item. below is the demo code from the polymer project. I understand this question may seem very simple to some of you. Thank you in advance for your patience and any assistance that may be provided.
<paper-menu-button>
<paper-icon-button icon="menu" noink></paper-icon-button>
<paper-dropdown class="dropdown">
<core-menu class="menu">
<template repeat="{{name in food}}">
<paper-item>{{}}</paper-item>
</template>
</core-menu>
</paper-dropdown>
</paper-menu-button>
there are several ways you can check a menu for user input.
method 1
you can use a EventListener to look for the core-select event. to do that you would give the core-menu a id. i am calling it select.
that would make the function look like
this.$.select.addEventListener('core-select', function () {
// access the value with this.selected
});
method 2
you could also use the declarative approach also using a EventListener but this time as a attribute on-core-select="{{selectAction}}" then the function would look like.
selectAction: function () {
// value would be this.$.select.selected if using the select id on the core-menu
}
method 3
you could also use a attribute changed function to get the value when changed. that method would look like.
<paper-menu-button>
<paper-icon-button icon="menu" noink></paper-icon-button>
<paper-dropdown class="dropdown">
<core-menu class="menu" selected="{{selected}}">
<template repeat="{{name in food}}">
<paper-item>{{}}</paper-item>
</template>
</core-menu>
</paper-dropdown>
</paper-menu-button>
the change would call a function that would look something like
selectedChanged: function () {
// value would be this.selected
}
i also made a plunker showing all 3 in use check console for output when selecting http://plnkr.co/edit/odQwNRLFTzyATodQUNh0?p=preview
edit: all this is assuming you are working inside a custom element. outside a custom element method 1 would still work. method 2 and 3 would require a auto-binding template
I'm very new to Polymer too, but I got tabs working this way (i think it may apply to drop-down too):
In normal web-pages:
<body>
<template is="dom-bind" id="app">
<div class="container">
<div class="menu-area">
<paper-tabs selected="{{selected}}" on-iron-select="_onTabSelected">
<template is="dom-repeat" items="[[items]]">
<paper-tab>[[item.name]]</paper-tab>
</template>
</paper-tabs>
</div>
</div>
</template>
<script>
app._onTabSelected = function (e) {
var selectedIndex = e.srcElement.selected;
var item = this.items[selectedIndex];
document.location = item.uri;
};
app.items = [
{id: 'HOME', name: 'Home', uri: "home.html"},
{id: 'PRODUCTS', name: 'Products', uri: "products.html"},
{id: 'USERS', name: 'Users', uri: "users.html"}
];
</script>
</body>
</html>
When composing new elements:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-tabs/paper-tabs.html">
<link rel="import" href="../../bower_components/paper-tabs/paper-tab.html">
<dom-module id="app-header-menu">
<template>
<div class="container">
<div class="menu-area">
<paper-tabs selected="{{selected}}" on-iron-select="_onTabSelected">
<template is="dom-repeat" items="[[items]]"><paper-tab>[[item.name]]</paper-tab></template>
</paper-tabs>
</div>
</div>
</template>
<script>
Polymer({
is: "app-header-menu",
properties: {
items: {
type: Array,
notify: false,
readOnly: false,
value: [
{id: 'HOME', name: 'Home', uri: "home.html"},
{id: 'PRODUCTS', name: 'Products', uri: "products.html"},
{id: 'USERS', name: 'Users', uri: "users.html"}
]
}
},
_onTabSelected: function (e) {
var selectedIndex = e.srcElement.selected;
var item = this.items[selectedIndex];
document.location = item.uri;
}
});
</script>
</dom-module>