My goal is to group a set of paper-checkbox.
For paper-ratio-button, I am doing:
<paper-radio-group selected="foo">
<paper-radio-button name="foo">Foo</paper-radio-button>
<paper-radio-button name="bar">Bar</paper-radio-button>
</paper-radio-group>
For paper-checkbox, I would have expected to use iron-selector:
<iron-selector attr-for-selected="name" selected="foo">
<paper-checkbox name="foo">Foo</paper-checkbox>
<paper-checkbox name="bar">Bar</paper-checkbox>
</iron-selector>
But this does not work, the checkbox with name=foo is not selected
I got it working, I was missing selected-attribute="checked":
<iron-selector attr-for-selected="name" selected="foo" selected-attribute="checked">
<paper-checkbox name="foo">Foo</paper-checkbox>
<paper-checkbox name="bar">Bar</paper-checkbox>
</iron-selector>
To allow multiple selection, use <iron-selector attr-for-selected="name" multi selected-values='["foo","bar"]' selected-attribute="checked">
You have to write your own little element. It's not that hard.. just something to start with:
parent
<my-el selected="foo">
<paper-checkbox name="foo"></paper-checkbox>
<paper-checkbox name="bar"></paper-checkbox>
<paper-checkbox name="foobar"></paper-checkbox>
</my-el>
my-el
<dom-module id="my-el">
<template>
<slot></slot>
</template>
<script>
Polymer({
is: 'my-el',
properties: {
selected: {
type: String,
observer: "_selectCheckboxes"
}
},
_selectCheckboxes() {
var checkboxes = this.$.slotted.getDistributedNodes();
this.reset(checkboxes);
for (var i = 0; i = checkboxes.length; i++) {
var obj = checkboxes[i];
if(obj.getAttribute("name") == value) {
obj.checked = true;
}
}
},
reset: function(obj) {
for (var i = 0; i = obj.length; i++) {
obj[i].checked = false;
}
return true;
}
});
</script>
</dom-module>
I hope that this will help you. Off course that you have to implement a little bit more logic to make it work. If you have more questions about it just ask, and i can edit my answer.
A little explanation: https://www.polymer-project.org/2.0/docs/upgrade
By the way: I assume you are using Polymer version >= 1.7.0. For older versions you have to use <content> element instead of <slot> and different selector
Related
From the Polymer Starter Kit prototype, I have a function from <my-view1>, which fires a function from the <my-app> through an event listener.
I want to be able to send some info along with that, so I have set up a data attribute which is captured in a variable.
How can I then send that variable to my main event listener and function in <my-app>?
<my-view1> Data attribute:
<paper-button raised on-tap="open" data-target="#dialog">Dialog</paper-button>
<my-view1> Function:
open: function(e) {
const target = e.target.dataset.target || e.target.parentElement.dataset.target;
this.fire('open-dialog'); //send target variable somehow?
}
<my-app> listener:
listeners: {
'open-dialog': 'handleOpenDialog' //get target variable from my-view1
}
<my-app> Function:
handleOpenDialog: function(e) {
console.log(target); //get target variable from listener
}
Thanks!
You could specify the event detail when calling fire(eventName, [detail], [options]). In your case, you'd pass target (the selector for the target dialog) in the event detail, and your event handler would query its children with that selector to fetch the dialog.
// my-view1
open: function(e) {
const target = e.target.dataset.target;
this.fire('open-dialog', target);
}
// my-app
handleOpenDialog: function(e) {
const target = e.detail;
const dialog = this.$$(target);
if (dialog) {
dialog.opened = true;
}
}
HTMLImports.whenReady(() => {
Polymer({
is: 'my-app',
listeners: {
'open-dialog': 'handleOpenDialog'
},
handleOpenDialog: function(e) {
const target = e.detail;
const dialog = this.$$(target);
if (dialog) {
dialog.opened = true;
}
}
});
Polymer({
is: 'my-view1',
open: function(e) {
const target = e.target.dataset.target;
this.fire('open-dialog', target);
}
});
});
<head>
<base href="https://polygit.org/polymer+1.7.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="paper-button/paper-button.html">
<link rel="import" href="paper-dialog/paper-dialog.html">
</head>
<body>
<my-app>
<my-view1></my-view1>
</my-app>
<dom-module id="my-app">
<template>
<content></content>
<paper-dialog id="dialog1">
<h2>Dialog 1</h2>
<div class="buttons">
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button dialog-confirm autofocus>Accept</paper-button>
</div>
</paper-dialog>
<paper-dialog id="dialog2">
<h2>Dialog 2</h2>
<div class="buttons">
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button dialog-confirm autofocus>Accept</paper-button>
</div>
</paper-dialog>
</template>
</dom-module>
<dom-module id="my-view1">
<template>
<paper-button on-tap="open" data-target="#dialog1">Dialog 1</paper-button>
<paper-button on-tap="open" data-target="#dialog2">Dialog 2</paper-button>
</template>
</dom-module>
</body>
codepen
I have Google Endpoints service with list-method what returned some data.
I can display this data in iron-list - everything is ok here.
But - since array of data is big - I like to return it from list by some "pages" - for example by 100 elements.
So, question is - how to fire getting new portion of data then iron-list will be scrolled down to the end of already received array? Any samples or suggestion on it?
iron-scroll-threshold is appropriate here. In the following example, _loadMoreData() is called when the iron-list is scrolled to 200px from the bottom, which in your case is where you'd query your Google Endpoints service to fetch more data.
// template
<iron-scroll-threshold id="threshold"
lower-threshold="200"
on-lower-threshold="_loadMoreData">
<iron-list scroll-target="threshold" items="[[items]]">
<template>
<div>[[index]]: [[item]]</div>
</template>
</iron-list>
</iron-scroll-threshold>
// script
Polymer({
...
_loadMoreData: function() {
var data = this.queryGoogleEndpointService();
// append data to `this.items`
}
}
<head>
<base href="https://polygit.org/polymer+1.11.1/iron-scroll-threshold+PolymerElements+:1.x/webcomponents+webcomponents+:v0/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="iron-list/iron-list.html">
<link rel="import" href="iron-scroll-threshold/iron-scroll-threshold.html">
<link rel="import" href="paper-progress/paper-progress.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<style>
iron-list {
height: 400px;
}
</style>
<iron-scroll-threshold id="threshold"
lower-threshold="200"
on-lower-threshold="_loadMoreData"
lower-triggered="{{nearBottom}}">
<iron-list scroll-target="threshold" items="[[items]]">
<template>
<div>[[index]]: [[item]]</div>
</template>
</iron-list>
</iron-scroll-threshold>
<template is="dom-if" if="[[nearBottom]]">
<paper-progress indeterminate></paper-progress>
</template>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
properties: {
items: {
type: Array,
value: function() { return []; }
}
},
_loadMoreData: function() {
console.log('loading 100 more...');
// simulate network delay
this.async(function() {
for (let i = 0; i < 100; i++) {
this.push('items', Math.random());
}
this.$.threshold.clearTriggers();
}, 500);
}
});
});
</script>
</dom-module>
</body>
codepen
I've established an array, like this:
<template>
<ul id="iconContainer" style="list-style: none; padding: 0; margin: 0;">
<template repeat="{{icon in icons}}">
<li class="flex icon-container"><app-icon label="{{icon.label}}" src="{{icon.src}}"></app-icon></li>
</template>
</ul>
</template>
<script>
Polymer('app-grid', {
ready: function() {
this.icons = [];
for(i = 1; i < 21; i++) {
this.icons.push({label: 'Item ' + i, src: '*'});
},
iconChanged: function() {
this.$.iconContainer.getElementsByTagName('template')[0].iterator_.updateIteratedValue();
}
});
</script>
And I'm getting frustrated on trying to find out how to alter this array from jquery on index.html as shown below to update the template.
<app-grid></app-grid>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).querySelector('app-grid').icons.push({label: 'foo', src: '*'});
</script>
This doesn't seem to work though.
Thoughts?
I'm not sure why you need jquery for this. The document.querySelector('app-grid') works just fine to get the element.
Before poking around at element properties, the element needs to have upgraded. The polymer-ready event is your signal that all elements are upgraded:
document.addEventListener('polymer-ready', function(e) {
document.querySelector('app-grid').icons.push({label: 'foo', src: '*'});
});
Demo: http://jsbin.com/wasafomesuba/1/edit
How to set list which is of parent element with this subscription data.?
Don't want to alter or add attribute to subscription element as it's independent of parent.
I got polymer element structure like this:
<polymer-element name="parent">
<polymer-element name="subscription" id="subscription">
<polymer-element>
<div id="list">
<template repeat="{{item in list}}">
<item name="{{item}}">
</item>
</template>
</div>
<script>
Polymer('parent', {
ready: function() {
this.list = this.list || [];
subscribe = this.$.subscription;
//Anytime if there is any change in subscription it send the data.
subscribe.addEventListener('data_from_subscription_element', function(x) {
// How to set list which is of parent element with this subscription data.?
// Don't want to alter or add attribute to subscription element as it's independent of parent.
this.data;
});
}
});
</script>
<polymer-element>
That looks like common problem of changing scope you are in. Try this:
<script>
Polymer('parent', {
ready: function() {
var that = this; // Giving the current scope to that;
this.list = this.list || [];
subscribe = this.$.subscription;
subscribe.addEventListener('data_from_subscription_element', function(x) {
that.list = this.data; // Using that here
});
}
});
</script>
I need to access the custom element and call its method from the click event callback.
<polymer-element name="my-element">
<template>
<style type="text/css" media="screen">
...
</style>
<ul id="my_data"></ul>
</template>
<script>
Polymer('my-element', {
dataSelected: function(selectedText) {
//...
},
setData: function(data) {
for (var i = 0; i < data.length; i++) {
var li = document.createElement('li');
li.addEventListener('click', function(e) {
// how can I call dataSelected() from here?
});
li.innerText = data[i];
this.$.my_data.appendChild(li);
}
}
});
</script>
</polymer-element>
How can I call the custom element's dataSelected() method from the callback?
You can use bind to attach a this context to any function, so:
li.addEventListener('click', function(e) {
this.dataSelected(e.target.innerText);
}.bind(this));
http://jsbin.com/xorex/4/edit
But you can make things easier by using more Polymer sugaring. For example, you can publish data and use the observation system, like so:
<polymer-element name="my-element" attributes="data">
...
data: [], // type hint that data is an array
...
dataChanged: function() { // formerly setData
http://jsbin.com/xorex/5/edit
Also, you can use the built-in event system instead of addEventListener
<polymer-element name="my-element" attributes="data">
...
<ul id="my_data" on-tap="{{dataTap}}"></ul>
...
dataTap: function(e) { // `tap` supports touch and mouse
if (e.target.localName === 'li') {
this.dataSelected(e.target.textContent);
}
}
http://jsbin.com/xorex/6/edit
But the biggest win is using <template repeat> instead of creating elements in JavaScript. At that point, the complete element can look like this:
<polymer-element name="my-element" attributes="data">
<template>
<ul id="my_data">
<template repeat="{{item in data}}">
<li on-tap="{{dataTap}}">{{item}}</li>
</template>
</ul>
</template>
<script>
Polymer('my-element', {
data: [],
dataTap: function(e) {
console.log('dataSelected: ' + e.target.textContent);
}
});
</script>
</polymer-element>
http://jsbin.com/xorex/7/edit
You could insert element = this; at the beginning of your setData() function and call element.dataSelected(); in the event handler.
But i think for what you want to achieve, you'd better use a repeat template (Iterative templates) and a direct binding to your click handler function (Declarative event mapping).