Creating a group of paper-checkbox (using iron-selector?) - polymer

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

Polymer Pass Variables from Element to Event Listener on another page

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

iron-list and load data with "pages"

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

Polymer: changing the array and template using JQuery

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

Polymer Event listener extract data

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>

How To Access Polymer Custom Element From Callback

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).