paper-menu-button - how read selected menu item - polymer

I'm searching for understanding how polymer works. How can I handle selecting menu item from list form that markup ?
<paper-menu-button icon="menu">
<div>kg</div>
<div>pcs</div>
<div>lt</div>
</paper-menu-button>

Here is an example for a popup menu that binds event functions to the menu items. It uses paper-items instead of divs, but divs would work as well.
<!doctype html>
<html>
<head>
<script src="../lib/platform/platform.js"></script>
<link href="../lib/core-icons/core-icons.html" rel="import">
<link href="../lib/paper-menu-button/paper-menu-button.html" rel="import">
<link href="../lib/paper-item/paper-item.html" rel="import">
</head>
<body unresolved>
<polymer-element name="my-menu">
<template>
<paper-menu-button icon="menu">
<paper-item on-tap="{{refresh}}">Refresh</paper-item>
<paper-item on-tap="{{help}}">Help</paper-item>
<paper-item on-tap="{{signOut}}">Sign out</paper-item>
</paper-menu-button>
</template>
<script>
Polymer('my-menu', {
refresh: function () { console.log('Refresh'); },
help: function () { console.log('Help'); },
signOut: function () { console.log('Sign out'); }
});
</script>
</polymer-element>
<my-menu></my-menu>
</body>
</html>

Related

Polymer 1.x: paper-tab inside paper-dialog not working

Here is the plunk.
My goal is to implement a paper-tabs + iron-pages pattern inside a paper-dialog.
When I click on the second tab I expect to see the content header of the tabbed pane read "Page 2" followed by the Lorem Ipsum text. But, instead, there is no content inside the second tabbed pane.
What am I missing?
http://plnkr.co/edit/wyk9jb8cD4nufYQMI3L8?p=preview
<link href="tab-a.html" rel="import">
<link href="tab-b.html" rel="import">
<base href="https://polygit.org/polymer+:master/iron-data-table+Saulis+:master/components/">
<link rel="import" href="polymer/polymer.html">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="paper-dialog/paper-dialog.html">
<link rel="import" href="paper-tabs/paper-tabs.html">
<link rel="import" href="iron-pages/iron-pages.html">
<dom-module id="content-el">
<template>
<style></style>
<button on-tap="open">Open Dialog</button>
<paper-dialog id="dialog" modal>
<h2>Dialog Title</h2>
<paper-tabs selected="{{selected}}">
<paper-tab>Tab 1</paper-tab>
<paper-tab>Tab 2</paper-tab>
</paper-tabs>
<iron-pages selected="{{selected}}">
<tab-a></tab-a>
<tab-b></tab-b>
</iron-pages>
</paper-dialog>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'content-el',
open: function() {
this.$.dialog.open();
},
});
})();
</script>
</dom-module>
Preset the selected tab
Otherwise your paper-tabs will initialize with no preselected tab.
Polymer({
is: 'content-el',
properties: {
selected: {
type: Number,
value: 0
}
},
open: function() {
this.$.dialog.open();
}
});
Fix your typo in tab-b declaration
Polymer({
// was previously `tabb`
is: 'tab-b'
});

Polymer 1.x: Imperatively accessing DOM nodes inside a dom-if template

Here is my jsBin.
I want to access by its id a DOM node inside a dom-if template. With my existing code, I expect to see true when attempting to cast these nodes to Booleans, but instead I get false (i.e., undefined).
Steps to recreate the problem:
Open this jsBin.
Understand that the HTML pane on the right is working correctly by showing Foo and Bar and not showing Baz.
Observe the console and understand the id="foo" node is accessible but the id="bar" and id="baz" elements are not. And this is my problem.
How can I access those nodes imperatively?
http://jsbin.com/kemoravote/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-form/iron-form.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<div id="foo">Foo</div>
<template is="dom-if" if="{{show}}">
<div id="bar">Bar</div>
</template>
<template is="dom-if" if="{{!show}}">
<div id="baz">Baz</div>
</template>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
show: {
type: Boolean,
value: function() {
return true;
}
}
},
attached: function() {
console.log('foo', !!this.$.foo);
console.log('bar', !!this.$.bar);
console.log('baz', !!this.$.baz);
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
The $ selector won't work. You have to use $$ as follows:
console.log('baz', !!this.$$('#baz'));
Here is the jsBin.
http://jsbin.com/xogediyato/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-form/iron-form.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<div id="foo">Foo</div>
<template is="dom-if" if="{{show}}">
<div id="bar">Bar</div>
</template>
<template is="dom-if" if="{{!show}}">
<div id="baz">Baz</div>
</template>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
show: {
type: Boolean,
value: function() {
return true;
}
}
},
attached: function() {
console.log('foo', !!this.$.foo);
console.log('bar', !!this.$.bar);
console.log('baz', !!this.$.baz);
console.log('bar', !!this.$$('#bar'));
console.log('baz', !!this.$$('#baz'));
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>

Polymer 1.x: Two-way databinding for paper-dropdown-menu

I want to set the paper-dropdown-menu to the value of 'Three' upon loading. I want to do this by data binding the value attribute of the paper-dropdown-menu to a sub property of the element called item.number which is set when registering the element. When I attempt this using the below code, the result I see is that the paper-dropdown-menu displayed value is just blank instead of reading 'Three'.
What code changes will achieve my desired behavior?
Follow these steps to reproduce the problem.
Open this JSBin.
Note the content of the display value of the dropdown menu is blank.
Click the button labeled Click to show item
Observe the console prints:
[object Object] {
number: "Three"
}
Understand the above steps demonstrate my desired behavior is not occurring.
Select the number "Four" in the dropdown menu.
Click the button labeled Click to show item
Observe the console prints:
[object Object] {
number: "Four"
}
Understand the above step shows one-way data binding is working on the element.
How can I achieve my desired behavior?
http://jsbin.com/loceqayezo/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-dropdown-menu/paper-dropdown-menu.html" rel="import">
<link href="paper-listbox/paper-listbox.html" rel="import">
<link href="paper-item/paper-item.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<p>
<button on-tap="show">Click to show item</button>
</p>
<paper-dropdown-menu label="Numbers"
value="{{item.number}}">
<paper-listbox class="dropdown-content">
<paper-item>One</paper-item>
<paper-item>Two</paper-item>
<paper-item>Three</paper-item>
<paper-item>Four</paper-item>
</paper-listbox>
</paper-dropdown-menu>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
item: {
type: Object,
notify: true,
value: function() {
return {number: "Three"};
},
},
},
show: function() {
console.log('item', this.item);
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
Your code doesn't work because value property of <paper-dropdown-menu> is read-only. See the documentation.
Instead you can bind to <paper-listbox selected>. With minimal changes you will have to bind to dropdown's element index.
Polymer({
is: "x-element",
properties: {
item: {
type: Object,
notify: true,
value: function() {
return {number: 2};
},
},
},
show: function() {
console.log('item', this.item);
},
});
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-dropdown-menu/paper-dropdown-menu.html" rel="import">
<link href="paper-listbox/paper-listbox.html" rel="import">
<link href="paper-item/paper-item.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<p>
<button on-tap="show">Click to show item</button>
</p>
<paper-dropdown-menu label="Numbers">
<paper-listbox class="dropdown-content"
selected="{{item.number}}">
<paper-item>One</paper-item>
<paper-item>Two</paper-item>
<paper-item>Three</paper-item>
<paper-item>Four</paper-item>
</paper-listbox>
</paper-dropdown-menu>
</template>
</dom-module>
<x-element></x-element>
</body>
To keep the full name in your item you can add an attribute to you selectable elements and use the attrForSelected property of paper-listbox.
Polymer({
is: "x-element",
properties: {
item: {
type: Object,
notify: true,
value: function() {
return {number: "Three"};
},
},
},
show: function() {
console.log('item', this.item);
},
});
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-dropdown-menu/paper-dropdown-menu.html" rel="import">
<link href="paper-listbox/paper-listbox.html" rel="import">
<link href="paper-item/paper-item.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<p>
<button on-tap="show">Click to show item</button>
</p>
<paper-dropdown-menu label="Numbers">
<paper-listbox class="dropdown-content"
selected="{{item.number}}"
attr-for-selected="data-item">
<paper-item data-item="One">One</paper-item>
<paper-item data-item="Two">Two</paper-item>
<paper-item data-item="Three">Three</paper-item>
<paper-item data-item="Four">Four</paper-item>
</paper-listbox>
</paper-dropdown-menu>
</template>
</dom-module>
<x-element></x-element>
</body>

Polymer 1.0 paper-menu with recursive template

This must be a useful and widely applied design to stack menus dynamically and from a custom element. I spent hours debugging this and come so far as some events (iron-select) are not being propagated [correctly].
In short
<paper-menu>
<mycustommenu data="menuJsonDefinition"></mycustommenu>
<paper-menu>
where mycustommenu renders paper-item or paper-submenu recursively,
so in the end it looks like
<PAPER-MENU>
<mycustommenu>
<PAPER-SUBMENU>
<PAPER-ITEM class="menu-trigger">submenutrigger</PAPER-ITEM>
<PAPER-MENU class="menu-content">
<PAPER-ITEM>xx</PAPER-ITEM>
</PAPER-MENU>
</PAPER-SUBMENU>
</mycustommenu>
</PAPER-MENU>
It WORKS so far. But as soon as we add recursion and replace inner
<PAPER-ITEM>xx</PAPER-ITEM>
with <mycustommenu> which renders to
<mycustommenu><PAPER-ITEM>xx</PAPER-ITEM></mycustommenu>
it doesn't click/select anymore
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/paper-styles/paper-styles.html">
<link rel="import" href="bower_components/paper-item/paper-item.html">
<link rel="import" href="bower_components/paper-menu/paper-submenu.html">
<link rel="import" href="bower_components/paper-menu/paper-menu.html">
</head>
<body>
<dom-module id="paper-treeitem">
<template>
<template is="dom-if" if="{{data.folder}}">
<paper-submenu>
<paper-item class="menu-trigger">{{data.name}}</paper-item>
<paper-menu class="menu-content" multi>
<template is="dom-repeat" items="{{data.children}}">
<!-- WORKING -->
<!-- COMMENT THIS LINE -->
<paper-item>{{item.name}}</paper-item>
<!-- NOT WORKING -->
<!-- UNCOMMENT THIS LINE -->
<!-- <paper-treeitem data="{{item}}"></paper-treeitem> -->
</template>
</paper-menu>
</paper-submenu>
</template>
<template is="dom-if" if="{{!data.folder}}">
<paper-item>{{data.name}}</paper-item>
</template>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'paper-treeitem',
properties: {
data: {
type: Object,
value: function() {
return {};
}
}
},
ready: function(){
console.log(this, this.data)
}
});
});
</script>
</dom-module>
<paper-menu>
<paper-treeitem id="tRootTreeItem"></paper-treeitem>
</paper-menu>
<script>
(function() {
window.z = document.querySelector("#tRootTreeItem");
z.data = {
name: "Root",
folder: true,
children: [{
name: "File 1"
}]
};
})()
</script>
</body>
</html>
I posted it at github as well https://github.com/PolymerElements/paper-menu/issues/93

Setting the height of core-pages elements?

I'm having a lot of trouble getting a core-pages element to have a non-zero height within my custom element. What is the best practice for having the core-pages height be the same as its selected content. Here's a trivial example which clearly breaks:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Polymer</title>
</head>
<body>
<script src="http://www.polymer-project.org/platform.js"></script>
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<link rel="import" href="http://www.polymer-project.org/components/core-pages/core-pages.html">
<polymer-element name="x-foo">
<template>
<core-pages id="pages" selected="{{selected}}">
<content></content>
</core-pages>
</template>
<script>
Polymer('x-foo', {
ready: function() {
this.selected = 0;
}
});
</script>
</polymer-element>
<polymer-element name="x-bar">
<template>
<div><content></content></div>
</template>
<script>
Polymer('x-bar', {});
</script>
</polymer-element>
<p>BEFORE</p>
<x-foo>
<x-bar>some text here</x-bar>
<x-bar>some other text here</x-bar>
</x-foo>
<p>AFTER</p>
</body>
</html>
And the jsbin to see the results: http://jsbin.com/xowoxakuwu/1/edit (notice how the core pages content overlaps with the next element)
This example shows a core-pages element within a custom element. The content that gets injected into the core-pages are also custom elements.
Whats the best practice here?
You can apply a style to the currently selected page in the x-foo element which sets display: block and position: relative so x-bar will inherit the height of it's content.
I've also added the "block" attribute to the x-foo element so it too inherits the height of the selected page. Other general attributes are here -> https://www.polymer-project.org/docs/polymer/layout-attrs.html#general-purpose-attributes
<script src="http://www.polymer-project.org/platform.js"></script>
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<link rel="import" href="http://www.polymer-project.org/components/core-pages/core-pages.html">
<polymer-element name="x-foo" block>
<template>
<style>
::content > .core-selected {
position: relative;
display: block;
}
</style>
<core-pages id="pages" selected="{{selected}}">
<content></content>
</core-pages>
</template>
<script>
Polymer('x-foo', {
ready: function() {
this.selected = 0;
}
});
</script>
</polymer-element>
<polymer-element name="x-bar">
<template>
<div>
<content></content>
</div>
</template>
<script>
Polymer('x-bar', {});
</script>
</polymer-element>
<p>BEFORE</p>
<x-foo>
<x-bar>some text here</x-bar>
<x-bar>some other text here</x-bar>
</x-foo>
<p>AFTER</p>