Polymer 1.0 paper-submenu(s) inside paper-menu - polymer

Then I select an item in my outer paper-menu and after that I navigate into my submenu and select an item there, the outer-item is still selected. also conversely:
<paper-menu class="list" attr-for-selected="data-route" selected="[[route]]" selectable="a">
<a data-route="one" href="{{baseUrl}}">
<iron-icon icon="home"></iron-icon>
<span>one</span>
</a>
<paper-submenu>
<paper-item class="menu-trigger">two</paper-item>
<paper-menu class="menu-content">
<a data-route="two-1" href="{{baseUrl}}two-1">
<paper-item>
<iron-icon icon="home"></iron-icon>
<span>two 1</span>
</paper-item>
</a>
<a data-route="two-2" href="{{baseUrl}}two-2">
<paper-item>
<iron-icon icon="info"></iron-icon>
<span>two 2</span>
</paper-item>
</a>
</paper-menu>
</paper-submenu>
<a data-route="users" href="{{baseUrl}}users">
<iron-icon icon="info"></iron-icon>
<span>Users</span>
</a>
<a data-route="contact" href="{{baseUrl}}contact">
<iron-icon icon="mail"></iron-icon>
<span>Contact</span>
</a>
</paper-menu>
Any idea how to fix it?

This can be done by programmatically managing the menu opened property via on-tap:
<dom-module id="menu-nav">
<template>
<!-- define route for 'view', e.g. /:view -->
<!-- define route for 'subview', e.g. /bar/:subview -->
<paper-menu selected="{{view}}" attr-for-selected="name">
<paper-item name="foo" on-tap="_onFoo">
Foo
</paper-item>
<paper-submenu opened="{{_isSubmenu(view, _inSubmenu)}}">
<paper-item on-tap="_onSubmenu" class="menu-trigger">
Bar
</paper-item>
<paper-menu selected="{{subview}}" attr-for-selected="subname" class="menu-content">
<paper-item subname="baz" on-tap="{{_onBar}}">
Baz
</paper-item>
<paper-menu>
</paper-submenu>
<paper-menu>
</template>
<script>
Polymer({
is: "menu-nav",
properties: {
view: {
type: String,
value: "foo"
},
_inSubmenu: {
type: Boolean,
value: false
}
},
_isSubmenu: function (view, _inSubmenu) {
return _inSubmenu || view === 'bar';
},
_onFoo: function () {
this.set('_inSubmenu', false);
// ... transition to next route, this could depend on the router being used
// for eample, with Excess router, this would be:
// Excess.RouteManager.transitionTo('/foo');
},
_onBar: function () {
this.set('_inSubmenu', true);
this.set('subview', undefined);
// ... transition to /bar/baz
},
_onSubmenu: function (e) {
e.stopPropagation();
this._onBar();
},
});
</script>
</dom-module>
Related issue: https://github.com/PolymerElements/paper-menu/issues/42

You can do this..
Add data-route attribute to your paper-submenu and bind it with the selected attribute of the nested paper-menu.
<paper-menu class="list" attr-for-selected="data-route" selected="[[route]]" selectable="a">
<a data-route="one" href="{{baseUrl}}">
<iron-icon icon="home"></iron-icon>
<span>one</span>
</a>
<paper-submenu **data-route="[[selectedMenuItem]]"**>
<paper-item class="menu-trigger">two</paper-item>
<paper-menu class="menu-content" **selected="{{selectedMenuItem}}"**>
<a data-route="two-1" href="{{baseUrl}}two-1">
<paper-item>
<iron-icon icon="home"></iron-icon>
<span>two 1</span>
</paper-item>
</a>
<a data-route="two-2" href="{{baseUrl}}two-2">
<paper-item>
<iron-icon icon="info"></iron-icon>
<span>two 2</span>
</paper-item>
</a>
</paper-menu>
</paper-submenu>
<a data-route="users" href="{{baseUrl}}users">
<iron-icon icon="info"></iron-icon>
<span>Users</span>
</a>
<a data-route="contact" href="{{baseUrl}}contact">
<iron-icon icon="mail"></iron-icon>
<span>Contact</span>
</a>
</paper-menu>

Related

Polymer Correct way to make sidemenu with submenu with icons

What is correct way to make sidemenu using paper-menu with list of items that use icons on the left and have submenus which too have icons.
<paper-menu>
<paper-submenu>
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Inbox
</paper-icon-item>
<paper-menu class="menu-content">
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 1
</paper-icon-item>
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 2
</paper-icon-item>
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 3
</paper-icon-item>
</paper-menu>
</paper-submenu>
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Second menu
</paper-icon-item>
</paper-menu>
Made this with Polymer Documentation and it is not working.
Following the <paper-submenu> docs, nested menus normally follow this pattern, where each expandable submenu has:
a paper-item (or equivalent) of class menu-trigger, which serves as the submenu's header
a paper-menu of class menu-content, which serves as the submenu's item container
<paper-menu>
<paper-submenu>
<paper-item class="menu-trigger">
Heading 1
</paper-item>
<paper-menu class="menu-content">
...
</paper-menu>
</paper-submenu>
</paper-menu>
It looks like your example was missing the menu-trigger class on your header items (i.e., "Inbox" and "Second menu").
<head>
<base href="https://polygit.org/polymer+1.2.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="paper-menu/paper-menu.html">
<link rel="import" href="paper-menu/paper-submenu.html">
<link rel="import" href="paper-item/paper-icon-item.html">
<link rel="import" href="iron-icon/iron-icon.html">
<link rel="import" href="iron-icons/iron-icons.html">
</head>
<body>
<style>
.menu-trigger {
color: blue;
}
</style>
<paper-menu>
<paper-submenu>
<paper-icon-item class="menu-trigger">
<iron-icon icon="inbox" item-icon></iron-icon>
Inbox
</paper-icon-item>
<paper-menu class="menu-content">
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 1
</paper-icon-item>
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 2
</paper-icon-item>
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 3
</paper-icon-item>
</paper-menu>
</paper-submenu>
<paper-submenu>
<paper-icon-item class="menu-trigger">
<iron-icon icon="inbox" item-icon></iron-icon>
Second menu
</paper-icon-item>
<paper-menu class="menu-content">
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 1
</paper-icon-item>
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 2
</paper-icon-item>
<paper-icon-item>
<iron-icon icon="inbox" item-icon></iron-icon>
Submenu 3
</paper-icon-item>
</paper-menu>
</paper-submenu>
</paper-menu>
</body>
jsbin

Polymer iron-list under polymer-tab not scrollable

We currently have an paper tab view with 3 tabs, each tab loads its own iron page. Inside the iron page we pull a list of elements using an API. The iron list successfully loads the api results but we can only view the first few elements.
The other elements are hidden as we are unable to scroll. How do we make the list scrollable? as the list view grows in size. The list is dynamically loaded when a particular tab is selected.
<paper-drawer-panel id="paperDrawerPanel">
<!-- Drawer Scroll Header Panel -->
<paper-scroll-header-panel drawer fixed>
<!-- Drawer Toolbar -->
<paper-toolbar id="drawerToolbar">
<span class="paper-font-title"><div class="logo"></div></span>
</paper-toolbar>
<!-- Drawer Content -->
<paper-menu class="list" attr-for-selected="data-route" selected="[[route]]">
<a data-route="home" href="/" >
<iron-icon icon="home"></iron-icon>
<span>Home</span>
</a>
<a data-route="todays-sminq" href="/todays-sminq" on-click="onDataRouteClick">
<iron-icon icon="info"></iron-icon>
<span>Today's sminq</span>
</a>
<a data-route="upcoming-sminq" href="/upcoming-sminq" on-click="onDataRouteClick">
<iron-icon icon="mail"></iron-icon>
<span>Upcoming sminq</span>
</a>
<a on-click="logOut">
<iron-icon icon="user"></iron-icon>
<span>Log Out</span>
</a>
</paper-menu>
</paper-scroll-header-panel>
<!-- Main Area -->
<paper-header-panel main condenses keep-condensed-header>
<!-- Main Toolbar -->
<paper-toolbar id="mainToolbar" class="small">
<paper-icon-button id="paperToggle" icon="menu" paper-drawer-toggle></paper-icon-button>
<span class="flex"></span>
<!-- Toolbar icons -->
<paper-icon-button icon="refresh"></paper-icon-button>
<paper-icon-button icon="search"></paper-icon-button>
<!-- Application name -->
<div class="middle middle-container center horizontal layout">
<div class="app-name">Sminq</div>
</div>
<!-- Application sub title -->
<!--<div class="bottom bottom-container center horizontal layout">-->
<!--<div class="bottom-title paper-font-subhead">waiting is now fun</div>-->
<!--</div>-->
</paper-toolbar>
<!-- Main Content -->
<div class="content">
<iron-pages attr-for-selected="data-route" selected="{{route}}">
<section data-route="home" >
<live-sminq ></live-sminq>
<!--paper-material elevation="1">
</paper-material>
<paper-material elevation="1">
</paper-material>
<paper-material elevation="1" class="paper-font-body2">
</paper-material-->
</section>
<section data-route="todays-sminq" id="sectiontodays" >
<todays-sminq></todays-sminq>
<!--paper-material elevation="1">
</paper-material-->
</section>
<section data-route="sminq-info">
<sminq-single
token_id ="{{params.id}}" token_number="{{params.no}}" user_name="{{params.name}}"
status_type="{{params.status}}"
user_mobile ="{{params.mobile}}"
queue_id ="{{params.queueId}}"
sminq_type="{{params.sminqType}}"
joinDate="{{params.date}}"
>
</sminq-single>
</section>
<section data-route="live-tokens"class="layout vertical fit">
<live-tokens
queue_id="{{params.id}}" user_name="{{params.name}}">
</live-tokens>
</section>
<section data-route="upcoming-sminq">
<upcoming-sminq>
</upcoming-sminq>
</section>
<section data-route="not-found">
<paper-material elevation="1">
<h2 class="page-title">Page Not Found</h2>
<p></p>
</paper-material>
</section>
</iron-pages>
</div>
</paper-header-panel>
</paper-drawer-panel>
This is our main index.html we have created separate module which loads the tabs and the list view
The code for this module is attached below
<iron-ajax
id="list"
headers='{"Authorization": "xxxx","X-Vertical-Type": "xxx" }'
content-type="application/json"
url=""
handle-as="json"
method="GET"
on-error="handleErr"
debounce-duration="300"
last-response="{{ liveQueues }}"
on-response="ajaxResponse">
</iron-ajax>
<!--<template auto is="dom-if" if="{{loading}}"style="width:100%;">-->
<!--<paper-progress value="10" indeterminate="true" ></paper-progress>-->
<!--</template>-->
<div></div>
<span style="display:none;">[[selected]]</span>
<paper-spinner id="spinner" alt="Loading tokens numbers" ></paper-spinner>
<paper-tabs id="scrollableTabs" selected={{selected}} scrollable >
<template is="dom-repeat" items="[[liveQueues]]" as="queue" >
<paper-tab on-click="listLiveTokens" >[[queue.queueName]]</paper-tab>
</template>
</paper-tabs>
<iron-pages selected="{{selected}}">
<template is="dom-repeat" items="[[liveQueues]]" as="queue" >
<paper-material elevation="1">
<iron-list items="[[queueTokens]]" as="token">
<template>
<div>
<div class="item" tabindex="0">
<span class="avatar" >[[token.tokenNumber]]</span>
<a href$="{{_getDetailsLink(token.tokenId,token.tokenNumber,token.userName,token.statusType,token.userMobile,token.joinDate)}}">
<div class="pad">
<div class="primary">[[token.userName]]</div>
<div class="secondary">[[token.userMobile]]</div>
<div class="secondary dim">[[token.notes]]</div>
<div class="secondary dim">[[token.joinTime]]</div>
</div>
</a>
<iron-icon icon$="[[iconForItem(sminq)]]"></iron-icon>
</div>
</div>
</template>
</iron-list>
</paper-material>
</template>
</iron-pages>
<iron-ajax
id="tokens"
headers='{"Authorization": "xxx","X-Vertical-Type": "xxxx" }'
content-type="application/json"
url=""
handle-as="json"
method="GET"
on-error="tokenError"
debounce-duration="300"
last-response="{{ queueTokens }}"
on-response="tokenResponse">
</iron-ajax>
<template is="dom-if" if="{{isQueueId}}">
<sminq-add queue_id="{{queueId}}"></sminq-add>
</template>
You can implement IronResizableBehavior to resize your list when you switch tabs (note: it should work by default though):
iron-list lays out the items when it receives a notification via the resize event. This event is fired by any element that implements IronResizableBehavior.
By default, elements such as iron-pages, paper-tabs or paper-dialog will trigger this event automatically. If you hide the list manually (e.g. you use display: none) you might want to implement IronResizableBehavior or fire this event manually right after the list became visible again. e.g.
document.querySelector('iron-list').fire('resize');

Polymer paper-tab select first tab programmatically

Our paper-tabs are generated dynamically, how can we select the first tab by default and also fire the change event so that the iron page content is visible.
<paper-tabs id="scrollableTabs" selected={{selected}} scrollable >
<template is="dom-repeat" items="[[liveQueues]]" as="queue" >
<paper-tab on-click="listLiveTokens" >[[queue.queueName]]</paper-tab>
</template>
</paper-tabs>
list: function() {
this.loading=!this.loading;
this.$.list.url = "http://apicall";
var tmp = this.$.list.generateRequest();
console.log(tmp)
},
this script fetches the tab content from the api call
<iron-pages selected="{{selected}}">
<template is="dom-repeat" items="[[liveQueues]]" as="queue" >
<paper-material elevation="1">
<iron-list items="[[queueTokens]]" as="token">
<template>
<div>
<div class="item" tabindex="0">
<span class="avatar" >[[token.tokenNumber]]</span>
<a href$="{{_getDetailsLink(token.tokenId,token.tokenNumber,token.userName,token.statusType,token.userMobile,token.joinDate)}}">
<div class="pad">
<div class="primary">[[token.userName]]</div>
<div class="secondary">[[token.userMobile]]</div>
<div class="secondary dim">[[token.notes]]</div>
<div class="secondary dim">[[token.joinTime]]</div>
</div>
</a>
<iron-icon icon$="[[iconForItem(sminq)]]"></iron-icon>
</div>
</div>
</template>
</iron-list>
</paper-material>
</template>
</iron-pages>
An event will fire every time the dom-repeat changes. You could listen to changes and set selected to 0.
<template is="dom-repeat" items="[[liveQueues]]" as="queue" on-dom-change="setSelected">
In your prototype you define the function.
setSelected: function() {
this.$.scrollableTabs.selected = 0;
}
Note that the function is called every time you update liveQueues and you may not want to reset the tabs every time.
The iron pages should update automatically, if you have data-binding to selected.
Well, I think that ready function is the way to initialize !
ready: function() {
this.selected = 0;
}

Polymer Navigation Drawer double click to open

I have followed the polymer demo to create a navigation drawer with a icon to open it on click. The demo only requires one click to open up the navigation drawer, but when I try it with my own code it required double clicks to open up. Any reason why? I have copied the code straight up from the demo. The function openDrawer() looks correct, but opening the drawers a double click. I don't know why it won't open on the first click.
<body fullbleed>
<template is="auto-binding" id="tmp">
<core-drawer-panel id="drawerPanel">
<core-header-panel drawer id="drawer" mode="seamed">
<core-toolbar id="navheader">
<span>Menu</span>
</core-toolbar>
<core-menu selected="{{option}}" valueattr="data-category">
</core-menu>
</core-header-panel>
<core-header-panel main id="main" mode="seamed">
<core-toolbar id="mainheader">
<paper-icon-button id="navicon" icon="menu" onclick="openDrawer()"></paper-icon-button>
<span flex>Booklet</span>
</core-toolbar>
</core-header-panel>
</core-drawer-panel>
</template>
<script>
document.addEventListener('polymer-ready', function() {
var pageStart = document.querySelector('#tmp');
pageStart.option = 'home';
});
function openDrawer() {
var navicon = document.getElementById('navicon');
var drawerPanel = document.getElementById('drawerPanel');
navicon.addEventListener('click', function() {
drawerPanel.togglePanel();
});
}
</script>
</body>
I see a few issues.
Because you have everything in an auto-binding template, you need to listen for template-bound instead of polymer-ready. Only when template-bound fires will your elements have been stamped to the DOM.
The other issue is that you're adding your click listener INSIDE your openDrawer method. You want to add the click listener in the template-bound handler.
Here's a jsbin example
<body fullbleed>
<template is="auto-binding" id="tmp">
<core-drawer-panel id="drawerPanel">
<core-header-panel drawer id="drawer" mode="seamed">
<core-toolbar id="navheader">
<span>Menu</span>
</core-toolbar>
<core-menu selected="{{option}}" valueattr="data-category">
<core-item>Foo</core-item>
<core-item>Bar</core-item>
<core-item>Baz</core-item>
</core-menu>
</core-header-panel>
<core-header-panel main id="main" mode="seamed">
<core-toolbar id="mainheader">
<paper-icon-button id="navicon" icon="menu"></paper-icon-button>
<span flex>Booklet</span>
</core-toolbar>
</core-header-panel>
</core-drawer-panel>
</template>
<script>
document.addEventListener('template-bound', function() {
var navicon = document.getElementById('navicon');
var drawerPanel = document.getElementById('drawerPanel');
navicon.addEventListener('click', function() {
drawerPanel.togglePanel();
});
});
</script>
</body>

Polymer How can I get core-item>core-button to access parent core-list model

I'm learning polymer and I've run into an issue where I have a core-list iterating on a datasource templating a paper-item that houses a core-icon-button.
<core-list id="list" fit>
<template>
<paper-item flex class="row {{ {selected: selected} | tokenList }}">
<core-icon-button id="settings"
icon="settings"
on-tap={{settingTap}}>
</core-icon-button>
{{model.Name}}
</paper-item>
</template>
</core-list>
The problem I am having is that on my buttons' on-tap function I need the parent items' model. Is there a "polymer way" to do what I am describing? Or do I have to extend
<polymer-element name='cust-list'>
<template>
<style>
</style>
<core-list id="list" fit data={{models}}>
<template>
<paper-item flex class="row {{ {selected: selected} | tokenList }}">
<core-icon-button id="settings" icon="settings" on-tap={{settingTap}}></core-icon-button>
{{model.name}}
</paper-item>
</template>
</core-list>
</template>
<script>
Polymer('cust-list', {
models: [{name: "test1"}, {name: "test2"}],
settingTap: function(e,d,s) {
console.log(s.templateInstance.model.model);
}
});
</script>
</polymer-element>
<cust-list></cust-list>