I have a very basic attempt at implementing paper-menu. However the rendered HTML is not right and breaks the interaction. When clicking a menu item, the entire list disappears. I've identified it's because the paper-item elements are not rendered inside a very key div inside the paper-menu element.
My component.html looks like this:
<div>
<paper-menu selected="0">
<paper-item>Location 1</paper-item>
<paper-item>Location 2</paper-item>
</paper-menu>
</div>
However, what gets rendered is like this:
<div>
<paper-menu role="menu" tabindex="0" selected="0" class="x-scope paper-menu-0">
<div class="selectable-content style-scope paper-menu">
</div>
<paper-item role="option" tabindex="0" aria-disabled="false" class="x-scope paper-item-0">Location 1</paper-item>
<paper-item role="option" tabindex="0" aria-disabled="false" class="x-scope paper-item-0">Location 2</paper-item>
</paper-menu>
</div>
If I manipulate the rendered HTML in the browser so the close div tag properly wraps the paper-item elements, the interaction works.
What am I doing wrong?
In my index.html I have:
<script src="lib/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="lib/paper-button/paper-button.html" />
<link rel="import" href="lib/paper-input/paper-input.html" />
<link rel="import" href="lib/paper-item/paper-item.html" />
<link rel="import" href="lib/paper-menu/paper-menu.html" />
<link rel="import" href="lib/paper-listbox/paper-listbox.html" />
<link rel="import" href="lib/paper-toggle-button/paper-toggle-button.html" />
<link rel="import" href="lib/paper-progress/paper-progress.html" />
<link rel="import" href="lib/paper-dropdown-menu/paper-dropdown-menu.html" />
And in my bower.json I am referencing the following versions
{
"name": "permit-manager-app",
"private": true,
"dependencies": {
"polymer": "^1.4.0",
"webcomponentsjs": "^0.7.22",
"paper-button": "^1.0.11",
"paper-input": "^1.1.10",
"paper-progress": "^1.0.9",
"paper-dropdown-menu": "1.2.1",
"paper-menu": "1.2.2",
"paper-item": "1.2.1",
"paper-listbox": "1.1.2",
"paper-toggle-button": "^1.1.2"
}
}
And this is Angular2 beta 17
I've come across a similar issue within the same project with the paper-dropdown-menu where a critical section is rendered out of place and the control does not function.
details are here:
Polymer paper-dropdown-menu not rendered correctly in browser
Related
I am very new to Polymer and I was trying use a paper-menu-button inside a paper-toolbar, to reproduce what was shown by Kevin Schaaf on Polymer Summit 2015, but it turns out that the element is not shown. Bellow is my code:
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/paper-toolbar/paper-toolbar.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../bower_components/paper-menu-button/paper-menu-button.html">
<dom-module id="input-header">
<template>
<paper-toolbar>
<paper-icon-button icon="mail"></paper-icon-button>
<div>{{title}}</div>
<paper-menu-button>
<paper-icon-button icon="more-vert"></paper-icon-button>
<paper-input label="Thread name:" value="{{title}}"></paper-input>
</paper-menu-button>
</paper-toolbar>
</template>
<script>
Polymer({
is: 'input-header',
properties: {
label: {
type: String,
notify: true
}
}
});
</script>
</dom-module>
What Am I doing wrong? Thanks in advance.
The classes are important. Also you don't have a paper-menu with the dropdown-content class defined. I'm not sure about having paper-input???
<paper-menu-button>
<paper-icon-button icon="menu" class="dropdown-trigger"></paper-icon-button>
<paper-menu class="dropdown-content">
<paper-item>Share</paper-item>
<paper-item>Settings</paper-item>
<paper-item>Help</paper-item>
</paper-menu>
</paper-menu-button>
I have no idea what you are trying. Using paper-input inside paper-menu-button which should show some items doesn't make point for me, but anyway, if you want to see paper-icon-button inside paper-menu-button you have to add dropdown-trigger class.
Code should be:
<paper-toolbar>
<paper-icon-button icon="mail"></paper-icon-button>
<div>{{title}}</div>
<paper-menu-button>
<paper-icon-button icon="more-vert" class="dropdown-trigger"></paper-icon-button>
<paper-input label="Thread name:" value="{{title}}"></paper-input>
</paper-menu-button>
</paper-toolbar>
paper-menu-button should have some dropdown content so that's why i don't get it.
Maybe use some wrap div around paper-icon-button and paper-input and set dropdown-trigger class to it
I just started learning Polymer and I'm trying to put entry and exit animation on a paper dialog. It seems like the entry animation works perfectly, but the exit animation is not. I'm do a workaround by manually coding a jQuery, but I would like to use the built in capability of paper dialog.
Thanks.
<paper-dialog id="dialog" entry-animation="slide-from-top-animation" exit-animation="fade-out-animation" class="dialogstyle" no-cancel-on-outside-click no-cancel-on-esc-key>
<div class="buttons">
<paper-button id="closebutton" dialog-dismiss autofocus><i class="fa fa-times" aria-hidden="true"></i></paper-button>
</div>
<strong>content here</strong>
</paper-dialog>
The exit animation should work as long as you remember to include the fade-out-animation.html.
<head>
<base href="https://polygit.org/polymer+1.11.1/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="paper-dialog/paper-dialog.html">
<link rel="import" href="neon-animation/web-animations.html">
<link rel="import" href="neon-animation/animations/slide-from-top-animation.html">
<link rel="import" href="neon-animation/animations/fade-out-animation.html">
</head>
<body>
<paper-dialog entry-animation="slide-from-top-animation"
exit-animation="fade-out-animation" opened>
<h2>Header</h2>
<div>Dialog body</div>
</paper-dialog>
</body>
codepen
I am having an issue with the rendered html for a simple paper-dropdown-menu. The list items do not appear as a styled "menu", but rather just a list of items appearing on the page.
Clicking the rendered paper-input component (part of the rendered dropdown) does animate the ripple, but does not animate the show/hide of the menu and menu items. Clicking an item in the list causes the list to disappear, but clicking the dropdown again does not make the list re-appear.
After examining the rendered html and comparing it with the same rendered demo html, I found that the paper-listbox and contained paper-items are rendered well outside of the iron-dropdown element where they should be. This causes all the non-functionality. By using the inspector and grabbing the paper-listbox html and moving it inside of the iron-dropdown fixes everything and the dropdown functions as expected.
What is causing the listbox to be rendered out of place?
Here is what the HTML that WORKS for a paper-dropdown-menu should look like:
...
<iron-dropdown id="dropdown" class="style-scope paper-menu-button" aria-disabled="false" horizontal-align="right" vertical-align="top" style="outline: none; z-index: 103; margin-bottom: 8px; margin-top: 8px; position: fixed; left: 137.938px; top: 317px;">
<div id="contentWrapper" class="style-scope iron-dropdown">
<div class="dropdown-content style-scope paper-menu-button" style="transform-origin: 0px 0px 0px; box-sizing: border-box; max-width: 104.063px; max-height: 218px;">
<paper-listbox role="listbox" tabindex="0" class="dropdown-content x-scope paper-listbox-0 x-scope paper-listbox-0" aria-expanded="true">
<paper-item role="option" tabindex="0" aria-disabled="false" class="x-scope paper-item-0 x-scope paper-item-0">CRV-6</paper-item>
<paper-item role="option" tabindex="-1" aria-disabled="false" class="x-scope paper-item-0 x-scope paper-item-0">M3 Turbo</paper-item>
<paper-item role="option" tabindex="-1" aria-disabled="false" class="x-scope paper-item-0 x-scope paper-item-0">919 Turbo</paper-item>
<paper-item role="option" tabindex="-1" aria-disabled="false" class="x-scope paper-item-0 x-scope paper-item-0">300</paper-item>
</paper-listbox>
</div>
</div>
</iron-dropdown>
</paper-menu-button>
</paper-dropdown-menu></div>
Working dropdown menu
But instead I see the following that DOES NOT WORK:
...
<iron-dropdown id="dropdown" class="style-scope paper-menu-button" aria-disabled="false" aria-hidden="true" horizontal-align="right" vertical-align="top" style="outline: none; display: none;">
<div id="contentWrapper" class="style-scope iron-dropdown">
<div class="dropdown-content style-scope paper-menu-button">
</div>
</div>
</iron-dropdown>
</paper-menu-button>
<paper-listbox role="listbox" tabindex="0" class="dropdown-content x-scope paper-listbox-0">
<paper-item role="option" tabindex="0" aria-disabled="false" class="x-scope paper-item-0">CRV-6</paper-item>
<paper-item role="option" tabindex="0" aria-disabled="false" class="x-scope paper-item-0">M3 Turbo</paper-item>
<paper-item role="option" tabindex="0" aria-disabled="false" class="x-scope paper-item-0">919 Turbo</paper-item>
<paper-item role="option" tabindex="0" aria-disabled="false" class="x-scope paper-item-0">300</paper-item>
</paper-listbox>
</paper-dropdown-menu>
</div>
Not working dropdown. Shows as list of items
Manually pushing the paper-listbox element and children into the div.dropdowncontent makes the control work perfectly. Also interesting, is making some seemingly non-descript white-space changes (in the inspector) causes a re-render of the section and either the whole paper-dropdown-menu element and children are removed, or the paper-listbox gets re-rendered in the correct place and the control works.
Any idea what could be driving the listbox element out of place?
Here is the source page.component.html that renders the dropdown
<div class="row">
<div class="col col-xs-12">
<paper-dropdown-menu label="Vehicle Model">
<paper-listbox class="dropdown-content">
<paper-item>CRV-6</paper-item>
<paper-item>M3 Turbo</paper-item>
<paper-item>919 Turbo</paper-item>
<paper-item>300</paper-item>
</paper-listbox>
</paper-dropdown-menu>
</div>
</div>
And the index.html with the references:
<!DOCTYPE html>
<html>
<head>
<title>Permit Management</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 1. Load libraries -->
<!-- IE required polyfills, in this exact order -->
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/router.dev.js"></script>
<script src="node_modules/angular2/bundles/http.js"></script>
<script src="node_modules/ng2-bs3-modal/bundles/ng2-bs3-modal.min.js"></script>
<script src="node_modules/moment/moment.js"></script>
<script src="node_modules/moment-timezone/builds/moment-timezone-with-data.min.js"></script>
<script src="lib/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="node_modules/font-awesome/css/font-awesome.css" />
<link rel="stylesheet" href="node_modules/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css" />
<link rel="import" href="lib/paper-button/paper-button.html" />
<link rel="import" href="lib/paper-input/paper-input.html" />
<link rel="import" href="lib/paper-item/paper-item.html" />
<link rel="import" href="lib/paper-menu/paper-menu.html" />
<link rel="import" href="lib/paper-menu-button/paper-menu-button.html" />
<link rel="import" href="lib/paper-dropdown-menu/paper-dropdown-menu.html" />
<link rel="import" href="lib/paper-listbox/paper-listbox.html" />
<link rel="import" href="lib/paper-checkbox/paper-checkbox.html" />
<link rel="import" href="lib/paper-toggle-button/paper-toggle-button.html" />
<link rel="import" href="lib/paper-progress/paper-progress.html" />
<link rel="import" href="lib/paper-spinner/paper-spinner-lite.html" />
<link rel="import" href="lib/gold-phone-input/gold-phone-input.html" />
<!-- 2. Configure SystemJS -->
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/main')
.then(null, console.error.bind(console));
</script>
<style is="custom-style">
#permitOwner {
--paper-input-container-input: {
font-size: 30px;
padding-left: 20px;
cursor: pointer;
};
}
#permitHolder {
--paper-input-container-input: {
padding-left: 20px;
cursor: pointer;
};
}
.plate-entry {
--paper-input-container-input: {
text-transform: uppercase;
};
}
</style>
<base href="/" />
</head>
<!-- 3. Display the application -->
<body>
<permit-manager-app>Loading...</permit-manager-app>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="styles.css">
</script>
</body>
</html>
bower.js package versions:
{
"name": "ASP.NET",
"private": true,
"dependencies": {
"polymer": "^1.5.0",
"webcomponentsjs": "^0.7.21",
"paper-button": "^1.0.11",
"paper-input": "^1.1.10",
"paper-progress": "^1.0.9",
"paper-dropdown-menu": "^1.2.1",
"paper-menu": "^1.2.2",
"paper-item": "^1.2.1",
"paper-listbox": "^1.1.2",
"paper-checkbox": "^1.2.0",
"paper-toggle-button": "^1.1.2",
"gold-phone-input": "^1.0.9",
"tether": "^1.3.2",
"tether-tooltip": "^1.2.0",
"requirejs": "^2.2.0",
"paper-spinner": "^1.1.1",
"web-animations-js": "^2.2.1"
},
"resolutions": {
"polymer": "^1.1.0"
}
ADDITIONAL INFO:
The paper-dropdown-menu renders and functions fine from the index.html. However does not from within a component and router-outlet.
This is due to how Polymer works with Shadow DOM. Even though some browsers support Shadow DOM natively, by default Polymer works in the “Shady DOM” mode. It doesn’t use Shadow DOM, but places the elements’s local DOM in a regular DOM tree, while applying scoping for the styles.
Unfortunately, this requires developers to always use Polymer.dom accessors to manipulate the DOM contents of Polymer elements. Angular 2 doesn’t know about that. In Angular 2 applications, component HTML templates are first compiled to JavaScript and then placed in DOM using regular browser DOM APIs.
To resolve this, you can try using Vaadin Angular2-Polymer package. It patches Angular 2 DomAdapter to use Polymer accessor functions for DOM manipulations. This keeps Polymer’s in-memory logical DOM tree in the right state and thus fixes the issue. I would recommend this way, the package also solves some other compatibility issues, such as: two-way data binding, styling and ngForm support.
Alternatively, you can switch Polymer to Shadow DOM mode by adding a line <script>window.Polymer = { dom: 'shadow' };</script> just after the webcomponentsjs script in the section. On the downside, in this mode it is required to have a support for Shadow DOM in browsers, either natively or with a full webcomponents.js polyfill, which has a performance impact.
I want to create my own <menu-item> element to remove some boilerplate code. I wrapped <paper-icon-item> in my own element in the following way:
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/paper-item/paper-icon-item.html">
<dom-module id="menu-item">
<template>
<paper-icon-item>
<iron-icon icon="[[icon]]" item-icon></iron-icon>
<content></content>
</paper-icon-item>
</template>
</dom-module>
<script>
Polymer({
is: "menu-item",
properties: {
icon: { type: String }
}
});
</script>
The problem when using my <menu-item> is, however, that it behaves differently as to writing the template code directly in the HTML file. I suspect that the item is missing some interaction capabilities with the menu to function properly, but I can't figure it out. I tried using behaviors Polymer.IronControlState and Polymer.IronButtonState just like the paper item does, but no luck.
What am I missing to make my <menu-item> behave like a regular <paper-item>?
Answer
Following code is largely copied from the paper-icon-item.html.
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/iron-behaviors/iron-control-state.html">
<link rel="import" href="bower_components/iron-behaviors/iron-button-state.html">
<link rel="import" href="bower_components/iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="bower_components/paper-styles/typography.html">
<link rel="import" href="bower_components/paper-styles/color.html">
<link rel="import" href="bower_components/paper-styles/default-theme.html">
<link rel="import" href="bower_components/paper-item/paper-item-behavior.html">
<link rel="import" href="bower_components/paper-item/paper-item-shared-styles.html">
<link rel="import" href="bower_components/iron-icon/iron-icon.html">
<link rel="import" href="bower_components/iron-icons/iron-icons.html">
<dom-module id="menu-item">
<template>
<style include="paper-item-shared-styles"></style>
<style>
:host {
#apply(--layout-horizontal);
#apply(--layout-center);
#apply(--paper-font-subhead);
#apply(--paper-item);
#apply(--paper-icon-item);
}
.content-icon {
width: var(--paper-item-icon-width, 56px);
#apply(--layout-horizontal);
#apply(--layout-center);
}
</style>
<div id="contentIcon" class="content-icon">
<iron-icon icon="{{ico}}" item-icon></iron-icon>
</div>
<content></content>
</template>
<script>
Polymer({
is: 'menu-item',
properties: {
ico: {
type: String,
value: "icons:stars"
}
},
behaviors: [
Polymer.PaperItemBehavior
]
});
</script>
</dom-module>
On Extending Elements
I think the simplest way of changing the template of an element is by just copying it, modifying the template and its name. This approach is not without problems, it becomes very difficult to keep the new element up to date with changes in the original one. I am really craving for a better solution!.
On Using Behaviors
You should try to avoid consuming both an element and a behavior used by that element at the same time, you might get into trouble. For example the reason your menu-item doesn't look proper is because the paper-item inside it doesn't acquire the attribute focused. The paper-item doesn't acquire that particular attribute is because its parent element menu-item has the focus, menu-item has the focus because both menu-item and paper-item have tabindex="0" set on them. Why do both these elements have it set on them?, it is because of Polymer.IronControlStateBehavior in both of them.
Using Polymer 1.0, I have created a paper-drawer-panel layout. In the drawer I have a menu using paper-menu with paper-items which are bound to the iron-pages. I took this example from Content Switcheroo with Core-Pages -- Polycasts #09 and converted it to use the Polymer 1.0 elements. In the code below you can see my commented section in which the paper-items are hard-coded. This works fine.
My next step was to try and build my menu dynamically by using the <template is="dom-repeat"> element to iterate over an arbitrary array of menu items. The menu is rendered correctly (I can see all the menu items that are bound to the array), but I cannot click on the items and no iron-pages are displayed. It seems that the data-category attribute which is used for attr-for-selected is not working inside <template is="dom-repeat">.
In what ways can I get this to work?
Edit: Removing the attr-for-selected attributes and switching the iron-pages using the index work, but relying on the index of the array is not an option in my situation.
My index.html is as follows:
<!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">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>My Test</title>
<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/iron-icons/iron-icons.html">
<link rel="import" href="bower_components/iron-pages/iron-pages.html">
<link rel="import" href="bower_components/paper-drawer-panel/paper-drawer-panel.html">
<link rel="import" href="bower_components/paper-toolbar/paper-toolbar.html">
<link rel="import" href="bower_components/paper-header-panel/paper-header-panel.html">
<link rel="import" href="bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="bower_components/paper-item/paper-item.html">
<link rel="import" href="bower_components/paper-styles/paper-styles.html">
<link rel="import" href="bower_components/paper-menu/paper-menu.html">
<style>
</style>
</head>
<body>
<my-app></my-app>
<dom-module id="my-app">
<style>
</style>
<template>
<paper-drawer-panel>
<paper-header-panel drawer class="fit">
<paper-toolbar>
<div>Drawer</div>
</paper-toolbar>
<paper-menu class="content fit" selected="{{page}}" attr-for-selected="data-category">
<!-- This works -->
<!--
<paper-item data-category="item1" label="item1">
<span>John Smith</span>
</paper-item>
<paper-item data-category="item2" label="item2">
<span>Jane Doe</span>
</paper-item>
-->
<!-- This does not work -->
<template is="dom-repeat" items="{{names}}">
<paper-item data-category="{{item.itemNum}}" label="{{item.itemNum}}">
<span>{{item.first}}</span><span>{{item.last}}</span><span>{{item.itemNum}}</span>
</paper-item>
</template>
</paper-menu>
</paper-header-panel>
<paper-header-panel main class="fit">
<paper-toolbar>
<paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
<div class="flex">Main Content</div>
</paper-toolbar>
<iron-pages selected="{{page}}" attr-for-selected="data-category">
<section data-category="item1">
<h1>Item 1</h1>
<div>Item 1 content...</div>
</section>
<section data-category="item2">
<h1>Item 2</h1>
<div>Item 2 content...</div>
</section>
</iron-pages>
</paper-header-panel>
</paper-drawer-panel>
</template>
<script>
Polymer({
is: "my-app",
ready: function() {
this.names = [{itemNum: "item1", first: "John", last: "Smith"}, {itemNum: "item2", first: "Jane", last: "Doe"}];
}
});
</script>
</dom-module>
</body>
</html>
Try <paper-item data-category$="{{item.itemNum}}" label$="{{item.itemNum}}">, from the docs, that will call paper-item.setAttribute('data-category', itemNum) instead of paper-item.data-category = itemNum.
https://www.polymer-project.org/1.0/docs/devguide/data-binding.html#attribute-binding