How to add a "Clear Button" into paper-dropdown-menu? - html

In a paper-input I have a "Clear Button":
<paper-input
id="myinput" maxlength="10" char-counter label="myinput"
always-float-label required>
<paper-icon-button suffix
onclick="clearInput('InputClientes')"
icon="clear"
class="iconClear"
alt="clear"
title="clear">
</paper-icon-button>
</paper-input>
It is possible to add a similar button (Clear Button) to a paper-dropdown-menu to clear the selection?.
Thanks.

1. If you use a paper-dropdown-button with a paper-listbox inside, you can call its selected property to null to clear the current value.
2. Add a button that will call this method and style it with a position:relative CSS rule to position it at the right place.
3. Listen for the iron-select event to show the [close] button when an item is selected in the list.
<paper-dropdown-menu id=PDM label="Your favourite pastry">
<paper-listbox id=PL class="dropdown-content">
<paper-item>Croissant</paper-item>
<paper-item>Donut</paper-item>
<paper-item>Financier</paper-item>
<paper-item>Madeleine</paper-item>
</paper-listbox>
</paper-dropdown-menu>
<paper-icon-button id=CloseBtn icon="clear" onclick="clearInput()" hidden ></paper-icon-button>
<script>
function clearInput() {
PL.selected = null
CloseBtn.hidden = true
}
PDM.addEventListener( 'iron-select', function ( ev ) {
CloseBtn.hidden = false
} )
</script>

Related

Select Item in Polymer 2 paper-dropdown-menu with TAB

I have a paper-dropdown-menu in Polymer 2, similar to this one:
<paper-dropdown-menu label="Dinosaurs">
<paper-listbox class="dropdown-content" selected="1">
<paper-item>allosaurus</paper-item>
<paper-item>brontosaurus</paper-item>
<paper-item>carcharodontosaurus</paper-item>
<paper-item>diplodocus</paper-item>
</paper-listbox>
</paper-dropdown-menu>
I can select an item of the paper-listbox by pressing the ENTER- Key on my Keyboard. Is there a way to select a paper-item by pressing the Tab key
You could add a key binding to <paper-listbox> via addOwnKeyBinding(). The specified handler must be a method of <paper-listbox>, so you'd have to attach your own method.
<paper-listbox id="listbox></paper-listbox>
// script
connectedCallback() {
super.connectedCallback();
// Attach our own handler for TAB-key
this.$.listbox._onListTabKey = e => {
// Cancel TAB key event
e.preventDefault();
e.stopPropagation();
e.detail.keyboardEvent.preventDefault();
// Select currently focused item
const focusedIndex = this.$.listbox.indexOf(this.$.listbox.focusedItem);
this.$.listbox.select(focusedIndex);
};
this.$.listbox.addOwnKeyBinding('tab', '_onListTabKey');
}
Polymer 1 demo
Polymer 2 demo
Note overriding TAB may be an accessibility issue.

Is there a common way to get a polymer element's dataset or attributes?

I used "paper-input" and "paper-button" in my own polymer element, since the e.target is not the element which bind the dataset and attributes, the way to get dataset in event handler is different. Is there a common way to get a polymer element's dataset or attributes?
<dom-module id="login-form">
<template>
<div>
<form action="/login" method="POST">
<paper-input id="username" >
<paper-icon-button on-click="clearInput" data-elmid="username" suffix >
</paper-icon-button>
</paper-input>
<paper-button class="custom indigo" data-hello="world" on-click="loginValidate">
Login
</paper-button>
</form>
</div>
</template>
<script>
(function() {
Polymer({
is: 'login-form',
clearInput: function(e) {
console.log(e.target.dataHost.dataset.elmid);
},
loginValidate: function(e) {
console.log(e.target.dataset.hello);
}
});
})();
</script>
</dom-module>
It looks like your binding is slightly incorrect.
To bind a data- attribute and be able to access it with the dataset property, use $= in data-foo$=value [*]. Otherwise, Polymer converts the attribute into a camelCase property on the element (i.e., data-foo= would be accessed by element.dataFoo, whereas data-foo$= would be element.dataset.foo).
In your example, Polymer created a dataElmid property on <paper-input>, and dataHello on <paper-button>.
Here's the corrected example:
<paper-input id="username">
<!-- change `data-elmid="username"` to `data-elmid$="username"` -->
<paper-icon-button on-click="clearInput" data-elmid$="username" suffix >
</paper-icon-button>
</paper-input>
<!-- change `data-hello="world"` to `data-hello$="world"` -->
<paper-button class="custom indigo" data-hello$="world" on-click="loginValidate">
Login
</paper-button>

Set selected item in paper-drop-down-menu?

I have this paper-dropdown-menu with one button:
<paper-dropdown-menu id="Default" label="My items">
<paper-menu id="DefaultDropDown" attr-for-selected="value" selected="{{selection}}" class="dropdown-content">
<paper-item value="5">Item 1</paper-item>
<paper-item value="6">Item 2</paper-item>
<paper-item value="7">Item 3</paper-item>
</paper-menu>
</paper-dropdown-menu>
<button onclick="clickEvent();">Click</button>
<script>
function clickEvent() {
$('#Default').selectedItem = -1;
}
</script>
I want in the event "clickEvent" you can set selection dropdown-menu to -1: noT selected item.
Any idea how?
The code I put javascript is only to illustrate the idea
The '#' here is redundant because $(...) only supports id anyway:
$('#Default').s...
The selection is maintained by the child component (<paper-menu>) in your case not the <paper-dropdown-menu> itself.
$('DefaultDropDown').selectIndex(-1);
I couldn't figure out from the docs whether deselecting is actually supported when multi is not set.

Polymer - How to fire events after paper-menu item was selected

I have a paper-menu with paper-items. Each item contains a paper-button. The paper-button click/tap event fires only if the button is not inside a selected paper-item.
<body>
<template is="dom-bind" id="root">
<paper-menu>
<paper-item>
Item 1
<paper-button id="button_1" on-tap="tapAction" raised>Button 1</paper-button>
</paper-item>
<paper-item>
Item 2
<paper-button id="button_2" on-tap="tapAction" raised>Button 2</paper-button>
</paper-item>
<paper-item>
Item 3
<paper-button id="button_3" on-tap="tapAction" raised>Button 2</paper-button>
</paper-item>
</paper-menu>
</template>
<script>
var root = document.querySelector("#root");
root.tapAction = function(e) {
console.log("tapAction: ", e.target.id)
};
</script>
</body>
See also:
http://plnkr.co/edit/vZk8gwLOxh6hxyiGPiu5
How can i trigger click/tap events on a Polymer component like paper-button after the menu item is selected?
The
<paper-item>
seems to be blocking the activation of your
<paper-button>
elements. You can overcome this in 2 ways. First you could use the iron-activate event of
<paper-menu>
like so
<paper-menu on-iron-activate="tapAction">
...
</paper-menu>
or you could remove the
<paper-item>
wrappers from around
<paper-button>
which will allow them to be activated.
<paper-menu>
<div>
Item 1 <paper-button id="button_1" on-tap="tapAction" raised>Button 1</paper-button>
</div>
<div>
Item 2
<paper-button id="button_2" on-tap="tapAction" raised>Button 2</paper-button>
</div>
<div>
Item 3
<paper-button id="button_3" on-tap="tapAction" raised>Button 2</paper-button>
</div>
</paper-menu>
And I don't think you need to worry about doing
var root = document.querySelector("#root");
as
<template is="dom-bind" id="root">
...
</template>
already does that for you, so you should be able to get away with just doing this
<script>
root.tapAction = function(e) {
console.log("tapAction: ", e.target.id)
};
</script>
UPDATE:
The solution of removing
<paper-item>
and replacing it with
<div>
has it's problems as once it's selected, the selected items button will no longer be able to be activated. Don't ask me why as I only just discovered this myself. The solution of iron-activate will still fire even when the item is selected but the event.target will be the
<paper-menu>
and while you could use the selected attribute to figure out which item is selected, it's always going to be one step behind the actual selected item. So if you selected item 1, then the selected will initially be undefined, unless you preselect an item
<paper-menu selected="0">
but even then, if you select another item, the selected item in the fired event will still be the previous one. You'll have to experiment, but I might suggest you try something else, as
<paper-menu>
might not fit the purpose you are wanting to use it for, if you're wanting to use
<paper-button>
elements.

Polymer 1.0: Clickable item in dom-repeat to e.g. iron-page which contains further info (contact list)

I'm setting up a contact list in Polymer 1.0. When the user clicks on a name, there should be a (animated) page opened for further details. All of these data elements are pulled from an external .json file.
Two questions for this approach..:
1) where to begin? How do I wrap, for example, an iron-page or neon-animated-page around my current setup (which is searchable, which is also the -temporary- reason it's a dom-repeat instead of an iron-list):
<template id="resultlist" is="dom-repeat" items="{{data}}" filter="contactFilter">
<paper-item>
<paper-item-body two-line>
<div>{{item.name}}</div>
<div secondary>{{item.number}}</div>
</paper-item-body>
</paper-item>
</template>
2) For quick try-out with binding options I've created an paper-dialog (instead of an page behaviour) which displays further data for the chosen person... On top of that paper-dialog should the chosen name being displayed. But I only get the first name of the array in my .json file. How can I setup the code to display the {{item.name}} of the chosen item?
Ps. I'm aware of the contacts-app from Rob Dodson (https://github.com/robdodson/contacts-app), but I can't figure out how it should be done in Polymer 1.0.
Update 27.10.2015
After Hugo's answer I'm not able to get the solution to work in an dom-module structure.
Sorry for misunderstanding, but I can't figure out where I'm wrong.
Having to following:
phonebook.html, which acts like an index
...
<body unresolved>
<template is="dom-bind" id="application">
<neon-animated-pages selected="[[selected]]" entry-animation="fade-in-animation" exit-animation="fade-out-animation">
<contact-list></contact-list>
<contact-details></contact-details>
</neon-animated-pages>
</template>
<script>
var application = document.querySelector('#application');
application.selected = 0;
document.addEventListener('show-details', function() {
application.selected = 1;
});
document.addEventListener('show-list', function() {
application.selected = 0;
});
</script>
</body>
DOM-module contact-list.html, the list it self.
<dom-module id="contact-list">
<template>
<style include="phonebook-styles"></style>
<iron-ajax url="../data/data.json" handle-as="json" last-response="{{data}}" auto></iron-ajax>
<div class="container">
<h3>Contactlist:</h3>
<div class="template-container">
<template is="dom-repeat" id="templateUsers" items="{{data}}">
<paper-item on-tap="showDetails">
<paper-item-body two-line>
<div>{{item.name}}</div>
<div secondary>{{item.phonenumber}}</div>
</paper-item-body>
<div class="item-details-link">
<iron-icon icon="account-circle"></iron-icon>
</div>
</paper-item>
</template>
</div>
</div>
</template>
<script>
Polymer({
is: 'contact-list',
properties: {
selectedContact:{
type:Object,
value:function(){
return null;
}
}
},
showDetails: function(ev) {
var data = this.$.templateUsers.itemForElement(ev.target);
//alert(JSON.stringify(data)) // works with data chosen data selection...
this.selectedContact = data;
this.fire('show-details', this.selectedContact);
}
});
</script>
</dom-module>
DOM-module contact-details.html, the details-list.
<dom-module id="contact-details">
<template>
<!-- Do I need to declare the .json in my details module? -->
<iron-ajax url="../data/data.json" handle-as="json" last-response="{{data}}" auto></iron-ajax>
<paper-icon-button icon="arrow-back" on-tap="showList"></paper-icon-button>
<h3>Contact details</h3>
<template is="dom-repeat" items="{{data}}">
<div>{{selectedContact.name}}</div>
</template>
</template>
<script>
Polymer({
is: 'contact-details',
showList: function() {
this.fire('show-list');
}
});
</script>
</dom-module>
Everything, like the transitions, work. The chosen contact is also displayed in an alertbox (commented out in contact-list.html), but isn't forwarded to the contact-details.html page.
There are multiple steps to implement the solution:
Setup the neon animated pages ( one page would be the contact list, the other page would be the details )
Display the list of contacts ( you already have this one )
Add a "selectedContact" property to your element
Add a tap/click handler to the list items element and inside the handler set the selectedContact. You need to get the contact item from the DOM element clicked. ( Check an example here : http://jsbin.com/lofarabare/6/edit )
You can bind the contact details page elements to the selectedContact properties, e.g {{selectedContact.name}}
Inside the handler also Change the neon animated pages selected property to have it display the animation to the other page.
-- Extra feedback
I checked the way you handle events, feedback below:
Give the elements some id so you can add the event listener directly to them (e.g application.$.myContactList.addEventListener('show-detail',function(ev){...})
The way you fire the event from the contact-list is correct, however you are not reading the event data inside the event listener for the 'show-detail' event. The event listener receives the event as argument "ev". You can get the event data using ev.detail
With the event data (the selected contact) you can update your contact details component. Give it some id like 'details' and just update the 'selectedContact' property. **You need to declare the selectedContact in the details component, right now you don't have it there **