Polymer 1.*
Is there a way to place a value other than the text in paper item that is used inside a paper-dropdown? For instance, when form is submitted I would like 50 instead of $50 dollars. I tried placing value='50' but the form still used the text $50 dollars.
<paper-dropdown-menu label="minimumPrice" name="minimumPrice">
<paper-listbox class="dropdown-content" selected="0">
<paper-item>No min</paper-item>
<paper-item>$50 dollars</paper-item>
There might be no official way to do that, but you could still technically accomplish your goal (with somewhat of a hack).
<paper-dropdown-menu> has an observer on its selectedItem that sets both its value and label to the same value (derived from the selected item); and the selectedItem is set by the <paper-dropdown-menu>'s event listener on iron-select, so you could add your own listener that overrides the label.
Here are the steps:
Specify the desired item value on each <paper-item>'s label attribute. Note the <paper-dropdown-menu> sets its value to the label of the selected item, but the text content of the <paper-item> still appears in the open dropdown menu (i.e., the listbox).
<paper-item label="0">No min</paper-item>
<paper-item label="50">$50 dollars</paper-item>
Add a listener for the iron-select event from <paper-dropdown-menu> in order to override the displayed label for the selected item.
ready: function() {
// <paper-dropdown-menu id="menu">
this.$.menu.addEventListener('iron-select', (e) => {
const paperItem = e.detail.item;
this.$.menu._setSelectedItemLabel(paperItem.textContent.trim());
});
}
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
_onResponse: function(e) {
const resp = e.detail.response;
this.response = JSON.stringify(resp, null, 2);
},
ready: function() {
this.$.menu.addEventListener('iron-select', (e) => {
const paperItem = e.detail.item;
this.$.menu._setSelectedItemLabel(paperItem.textContent.trim());
});
}
});
});
<head>
<base href="https://polygit.org/polymer+1.10.1/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="neon-animation/web-animations.html">
<link rel="import" href="iron-form/iron-form.html">
<link rel="import" href="paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="paper-listbox/paper-listbox.html">
<link rel="import" href="paper-item/paper-item.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<iron-form id="myForm" on-iron-form-response="_onResponse">
<form action="https://httpbin.org/get">
<paper-dropdown-menu id="menu" label="Minimum Price" name="minimumPrice">
<paper-listbox slot="dropdown-content" class="dropdown-content">
<paper-item label="0">No min</paper-item>
<paper-item label="50">$50 dollars</paper-item>
<paper-item label="100">$100 dollars</paper-item>
<paper-item label="200">$200 dollars</paper-item>
</paper-listbox>
</paper-dropdown-menu>
<button type="submit">Submit</button>
</form>
</iron-form>
<pre>[[response]]</pre>
</template>
</dom-module>
</body>
codepen
Try
<paper-item value="50" selected>$50 dollars</paper-item>
This would select the $50 dollars as default and should grab the value
You can add label property in paper-item to get the desired result.
<paper-dropdown-menu label="minimumPrice" name="minimumPrice">
<paper-listbox id="test" slot="dropdown-content" class="dropdown-content" selected="0">
<paper-item label="0">No min</paper-item>
<paper-item label="50">$50 dollars</paper-item>
</paper-listbox>
</paper-dropdown-menu>
The value property in paper-dropdown-menu will always have the same value as of selectedItemLabel and the selectedItemLabel contains the value derived from the "label" of the currently selected item if set, or else the trimmed text content of the selected item.
Update
Another way:
Create a hidden input and assign the selected value to the hidden input's value.
<paper-dropdown-menu label="minimumPrice" >
<paper-listbox slot="dropdown-content" class="dropdown-content" selected="{{selected}}" attr-for-selected="value">
<paper-item value="0">No min</paper-item>
<paper-item value="50">$50 dollars</paper-item>
</paper-listbox>
</paper-dropdown-menu>
<input is="iron-input" name="minimumPrice" id="hiddenSelected" type="hidden" value="[[selected]]">
And if you want first content to be selected by default you can assign inside ready function:
ready: function(){
this.selected = 0;
}
Related
I am trying to show a paper-dropdown-menu only when a specific value is selected in another paper-dropdown-menu.
I am using a property called selectedValue to bind selected value to the if attribute in a dom-if template.
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="../bower_components/polymer/lib/elements/dom-if.html">
<link rel="import" href="../bower_components/polymer/lib/elements/dom-repeat.html">
<link rel="import" href="../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="../bower_components/paper-listbox/paper-listbox.html">
<link rel="import" href="../bower_components/paper-item/paper-item.html">
<dom-module id="my-element">
<template>
<paper-dropdown-menu label="One" no-animations>
<paper-listbox slot="dropdown-content" class="dropdown-content" selected="{{selectedValue}}">
<template is="dom-repeat" items="[[options1]]">
<paper-item>[[item]]</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
<template is="dom-if" if="[[_view()]]">
<paper-dropdown-menu label="Two" no-animations>
<paper-listbox slot="dropdown-content" class="dropdown-content">
<template is="dom-repeat" items="[[options2]]">
<paper-item>[[item]]</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
</template>
</template>
<script>
/**
* #customElement
* #polymer
*/
class MyElement extends Polymer.Element {
static get is() { return 'my-element'; }
static get properties() {
return {
selectedValue : {
type : String
},
options1 : {
type: Array,
value: [1,2,3,4]
},
options2 : {
type: Array,
value : [5,6,7]
}
};
}
_view() {
return this.selectedValue === "1";
}
}
window.customElements.define(MyElement.is, MyElement);
</script>
</dom-module>
The problem is the second paper-dropdown-menu is never displayed.
The problem is your computed binding has no dependencies, so it's invoked once at initialization. Since selectedValue is initially undefined, _view() returns false, causing the dom-if to hide its contents.
To cause the computed binding to re-evaluate selectedValue, make sure to specify the variable as an argument to the binding:
<template is="dom-if" if="[[_view(selectedValue)]]">...</template>
Also note that <paper-listbox>.selected (to which selectedValue is bound) is a number by default (i.e., the index of the selected item), so this expression always evaluates to false:
selectedValue === "1"
I recommend switching the literal from a string to a number:
selectedValue === 1
So, the _view function should look like this:
_view(selectedValue) {
return selectedValue === 1;
}
demo
I have a Polymer element that uses <template is="dom-if"... to provide different HTML content depending on a condition.
Polymer dom-if has no else condition, so needs a negative if condition to simulate it.
Something like this:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<dom-module id="test-thing">
<template>
<template is="dom-if" if="{{title}}" restamp>
<b>[[title]]</b>
</template>
<template is="dom-if" if="{{!title}}" restamp>
<i>no title</i>
</template>
</template>
<script>
Polymer({
is: 'test-thing',
properties: {
title: String
}
});
</script>
</dom-module>
<div>
With negative condition:
<test-thing></test-thing>
</div>
<div>
With positive condition:
<test-thing title="Has Title"></test-thing>
</div>
Only that doesn't work - the negative condition never passes.
How should this be implemented?
You must use a default empty value for your title property:
title:{type: String,value:''}
Like so:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<dom-module id="test-thing">
<template>
<template is="dom-if" if="{{title}}" restamp>
<b>[[title]]</b>
</template>
<template is="dom-if" if="{{!title}}" restamp>
<i>no title</i>
</template>
</template>
<script>
Polymer({
is: 'test-thing',
properties: {
title: {type: String,value:''}
}
});
</script>
</dom-module>
<div>
With negative condition:
<test-thing></test-thing>
</div>
<div>
With positive condition:
<test-thing title="Has Title"></test-thing>
</div>
I'm adding some items to an Array, using the Array mutation methods. The items are displayed within a <dom-repeat> and can can be edited on the fly. While the edits do change the data in the object, any attached observers do not fire to indicate that a change occurred.
tl;dr
I'm properly using the Array mutation methods to push items
this.push("data.contents", {
id: 1,
name: "Modifying this text doesn't trigger an observer"
});
I'm displaying the items in a dom-repeat
These items are displayed using a <dom-repeat>, and the sub-property name is displayed in a <paper-input> where they can be amended on the fly.
<template>
<template is="dom-repeat" items="[[data.contents]]">
<paper-input value="{{item.name::input}}"></paper-input>
</template>
</template>
It seems that while the data is modified in the object itself, any attached observers do not fire for these sub-properties.
I'm attaching wildcard observers
I'm observing using the usual wildcard observers like so:
observers: [
"logChange(data.*)"
],
Notes
Note that:
Changing the item via a direct this.set() like so:
this.set("data.contents.0.name", "Foo")
will trigger the observers just fine
An MCVE for the above.
How to use:
Press the button to push some items to the Array
Edit any one of the added items
Console should log that a change occurred in any of the items (it doesn't)
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<link href="paper-button/paper-button.html" rel="import">
<dom-module id="x-example">
<template>
<paper-button on-tap="pushItem">Push to Array</paper-button>
<template is="dom-repeat" items="[[data.contents]]">
<paper-input value="{{item.name::input}}"></paper-input>
</template>
</template>
<script>
HTMLImports.whenReady(function() {
"use strict";
Polymer({
is: "x-example",
properties: {
data: {
type: Object,
value: {
contents: []
}
}
},
observers: [
"logChange(data.*)"
],
pushItem: function() {
this.push("data.contents", {
id: 1,
name: "Modifying this text doesn't trigger an observer"
})
},
logChange: function() {
console.log("change occured!");
}
});
});
</script>
</dom-module>
<x-example></x-example>
Solved here: https://github.com/Polymer/polymer/issues/4140#issuecomment-259465035
The observer isn't firing because you have one-way binding annotations on the items property, which prevents change notifications from flowing up to the element. Change it to: items="{{data.contents}}" and you'll see the changes.
In essence, turn this:
<template is="dom-repeat" items="[[data.contents]]">
<paper-input value="{{item.name::input}}"></paper-input>
</template>
to this
<template is="dom-repeat" items="{{data.contents}}">
<paper-input value="{{item.name::input}}"></paper-input>
</template>
How can I use <template is="dom-bind"> within <test-fixture> with web-components-tester?
I have tried to use it Polymer 0.8 x-template way:
<test-fixture id="dom-bind-fixture">
<template is="dom-bind">
<h1>{{greeting}}</h2>
</template>
</test-fixture>
<script>
// ...
var bound = fixture('dom-bind-fixture', {greeting: 'ohai thurr'});
</script>
which naturally fails, as dom-bind does not have stamp method.
Then, I tried just stamping it out of native <template> element:
<test-fixture id="dom-bind-fixture">
<template>
<h1>outside dom-bind</h1>
<template is="dom-bind">
<h2>inside dom-bind</h2>
</template>
</template>
</test-fixture>
But in non-Chrome browsers this one stamps only outside dom-bind.
Is there a way to make it work, or is it just a blocking bug in web-components-tester/test-fixture/dom-bind?
Use dom-template, ie:
<test-fixture id="dom-bind-fixture">
<template is="dom-template">
<h1>{{greeting}}</h2>
</template>
</test-fixture>
<script>
// ...
var bound = fixture('dom-bind-fixture', {greeting: 'ohai thurr'});
</script>
Is something like this posible outside a Polymer element?
I want to be able to get data from a json and insert it as menu items, but what works fine inside a polymer element won't work here. Is there something I'm missing or this is impossible?
<html>
<head>
[...]
</head>
<body>
<core-toolbar>
<paper-menu-button id="dropDownMenu">
<paper-icon-button id="iconomenuback" icon="menu" noink></paper-icon-button>
<paper-dropdown class="dropdown colored" halign="left">
<core-menu class="menu">
<paper-item>Escritorio</paper-item>
<template is="auto-binding">
<custom-item-list id="list" items={{items}} jsonurl="postsESTADO CIVIL.json"></custom-item-list>
<hr />
<template is="auto-binding" repeat="{{item in items}}">
<paper-item>
{{item.name}}
</paper-item>
</template>
<%--<asp:Literal ID="MainMenuItems" runat="server"></asp:Literal>--%>
<hr />
</template>
<paper-item>Panel de Control</paper-item>
</core-menu>
</paper-dropdown>
</paper-menu-button>
</core-toolbar>
</body>
</html>
EDIT
I'm trying a new approach, as seen in the Polymer Single Page Application.
So far I'm still stuck. This is how my code looks right now:
<paper-menu-button id="dropDownMenu" style="display:none;">
<paper-icon-button id="iconomenuback" icon="menu" noink></paper-icon-button>
<paper-dropdown class="dropdown colored" halign="left">
<core-menu class="menu">
<paper-item onclick="menuBackClick()">Escritorio</paper-item>
<hr />
<template repeat="{{menuit, i in menuits}}">
<paper-item>
{{menuit.Name}}
</paper-item>
</template>
<%--<asp:Literal ID="MainMenuItems" runat="server"></asp:Literal>--%>
<hr />
<paper-item onclick="panercontrol()">Panel de Control</paper-item>
</core-menu>
</paper-dropdown>
</paper-menu-button>
And this is the script I'm using, it gets the json from a file, extracts the data from it and then uses it.
<script>
$.getJSON('api/mainmenu.json', function (data) {
var template = document.querySelector('#fulltemplate');
var itemsstring = JSON.stringify(data);
template.menuits = itemsstring;
});
</script>
At the moment it doesn't do anything, inspecting it returns plain <template repeat="{{menuit, i in menuits}}"></template> with nothing in it.
The #fulltemplate Template wraps all the content inside the body.