I have the following pseudo component structure:
<polymer-element ...>
<parent-custom-element>
<custom-tableview-element data="{{data}}"></custom-tableview-element>
</parent-custom-element>
<script>
ready: function () {
this.data = [{ actionButtons: [{ icon: "send" , action: this.onSendAction() },
{ icon: "delete" , action: this.onDeleteAction() }]
},
{ actionButtons: [{ icon: "add" , action: this.onAddAction() },
{ icon: "edit" , action: this.onEditAction() }]]
}];
},
onSendAction : function (e, detail, sender) {
console.log("onSendAction tapped...");
},
onDeleteAction : function (e, detail, sender) {
console.log("onDeleteAction tapped...");
},
onAddAction : function (e, detail, sender) {
console.log("onAddAction tapped...");
},
onEditAction : function (e, detail, sender) {
console.log("onEditAction tapped...");
},
</script>
</polymer-element>
Then the custom-tableview-element is a core-list with a paper-icon-button as follow:
<polymer-element name="custom-tableview-element">
<template>
<core-list id="list" data="{{data}}" selectionEnabled="{{selectionEnabled}}"
selection="{{selection}}" height="80" flex multi?={{multi}} style="height:400px;">
<template>
<paper-icon-button icon="{{model.icon}}"
on-tap="{{model.action}}">
</template>
</core-list>
</template>
<script>...</script>
....
Is it possible to call the parent-actions, (e.g onSendAction or onAddAction) from this paper-icon-button?
It's not possible to call it directly from inside the element, because it's encapsulated inside shadow dom. But you could try to attach the function to global variable like window.
Related
how can I use dom-repeat to create different elements for iron-pages? something like this:
<template is="dom-repeat" items="{{pages}}">
<[[item.name]]></[[item.name]]>
</template>
...
pages: {
type: Array,
value() {
return [
{
"name": "element-a",
},
{
"name": "element-b",
},
{
"name": "element-c",
},
},
I'm using polymer 2.0.
since my comment had some interest, I put it as an answer.
The code examples will be in polymer 1.9 for now, I'll update my answer when I'll do the switch to 2.0 but the idea should be the same anyway
First you need a wrapper element, wich will be capable of creating another element dynamically from a property, and adding it to itself.
In my example the name of the element to create will be a property named type of a JSON object Data wich came from a database in XHR.
With a dynamically created element the binding won't work, so you have to do it by hand. That's what the _updateStatefunction is for, here it only update on one property but the idea is the same is there is more.
wrapper :
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../styles/shared-styles.html">
<dom-module id="element-wrapper">
<template></template>
<script>
Polymer({
is: 'element-wrapper',
properties: {
elementData: {
type: Object
},
saveFbPath: {
type: String
},
element: {
type: Object
},
formSubmitPressed: {
type: Boolean,
value: false
}
},
observers: [
'_updateState(elementData.*)'
],
attached: function () {
console.log("creating element : ", this.elementData);
this.async(function () {
this.element = this.create(this.elementData.type, {
"data": this.elementData
});
this.appendChild(this.element);
}.bind(this));
},
_updateState: function (elementData) {
if (typeof this.element !== "undefined") {
this.element.data = elementData.value;
console.log('Change captured', elementData);
}
}
});
</script>
</dom-module>
The this.element = this.create(this.elementData.type, {"data":this.elementData}); line is the one creating the element, first argument is the dom-modulename, and the second a JSON object wich will be binded to the properties of the element.
this.appendChild(this.element);will then add it to the dom
All this is in a this.async call for a smoother display
You then need a dom-repeat which will call this element, and give it the datas it need to create the dynamic ones.
Here is an example of an element-list but you don't necessary need a specific element for that, this logic can be in a bigger one.
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../styles/shared-styles.html">
<link rel="import" href="element-wrapper">
<dom-module id="element-list">
<template>
<style is="custom-style" include="shared-styles"></style>
<template is="dom-repeat" items="[[ datas ]]" initial-count="10" as="data">
<element-wrapper element-data="[[data]]"></element-wrapper>
</template>
</template>
<script>
Polymer({
is: 'element-list',
properties: {
datas: {
type: Array,
value: function () {
return [];
}
}
}
});
</script>
</dom-module>
This should do the trick :)
Polymer dom-repeat is not working as expected, when I add a new element to the Array dynamically, dom-repeat not displaying the value.
I am using the Polymer's array mutation methods when pushing items into the array, but still not working.
Please check the codepen link;
<dom-module id="wind-studio-widget">
<template>
<div on-tap='_addNewPad' style="cursor:pointer"><strong>Click Me</strong></div>
<template id="padListContainerId" is="dom-repeat" items="[[padList]]">
<p style="border:1px solid red"> <span>[[item.id]]</span></p>
</template>
</template>
</dom-module>
<script type="text/javascript">
Polymer({
is: 'wind-studio-widget',
properties: {
baseUrl: {type: String},
padList: {
type: Array,
notify: true
},
padListAverage: {type: Object}
},
ready: function () {
//this.baseUrl = localStorage.baseUrl;
//this.loadPadData();
this.padList = [{'id':'1'},{'id':'2'}];
},
_addNewPad: function () {
var newPadList = this.padList;
newPadList.push({'id':'3'});
this.set('padList', []);
this.set('padList', newPadList);
console.log(this.padList);
//this.$.padListContainerId.render();
}
});
</script>
http://codepen.io/nareshchennuri/pen/vxjvdO
The current code is below. I have element-value in the main file. This value is passed to the child elements app-element and from there to app-element-add.
The value changes in app-element-add. But I cannot get the value reflected in the main element.
The observers never get invoked.
main.html
<app-element element-value = {{ elementValue }}></app-element>
Polymer({
is: 'app-main-element',
properties: {
elementValue: {
type:Array,
notify:true,
observer:'listUpdated'
}
});
app-element.html
<app-element-add element-value = {{ elementValue }}></app-element-add>
Polymer({
is: 'app-element',
properties: {
elementValue: {
type:Array,
notify:true,
observer:'listUpdated'
}
});
app-element-add.html
Polymer({
is: 'app-element-add',
properties: {
elementValue: {
type:Array,
notify:true,
reflectToAttribute:true
}
});
Any hints on how to reflect changes in app-element-add in app-main-element. Thanks.
You don't need to use reflectToAttribute here. The only option required here is notify. However, your current code works:
HTMLImports.whenReady(_ => {
"use strict";
Polymer({
is: 'app-main-element',
properties : {
elementValue: {
type: Array,
notify: true,
observer: 'listUpdated',
value: _ => [100,200,300]
}
},
listUpdated: function() {
console.log('[app-main-element] list updated');
},
ready: function() {
console.log('[app-main-element] ready');
}
});
Polymer({
is: 'app-element',
properties : {
elementValue: {
type: Array,
notify: true,
observer: 'listUpdated'
}
},
listUpdated: function() {
console.log('[app-element] list updated');
},
ready: function() {
console.log('[app-element] ready');
}
});
Polymer({
is: 'app-element-add',
properties : {
elementValue: {
type: Array,
notify: true
}
},
ready: function() {
console.log('[app-element-add] ready (will set elementValue in 1000ms)');
this.async(_ => {
console.log('[app-element-add] updating elementValue');
this.elementValue = [1,2,3];
}, 1000);
}
});
});
<head>
<base href="https://polygit.org/polymer+1.11.0/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<app-main-element></app-main-element>
<dom-module id="app-main-element">
<template>
<app-element element-value={{elementValue}}></app-element>
<div>app-main-element.elementValue = [[elementValue]]</div>
</template>
</dom-module>
<dom-module id="app-element">
<template>
<app-element-add element-value={{elementValue}}></app-element-add>
<div>app-element.elementValue = [[elementValue]]</div>
</template>
</dom-module>
<dom-module id="app-element-add">
<template>
<div>app-element-add.elementValue = [[elementValue]]</div>
</template>
</dom-module>
</body>
codepen
In 0.5 it was possible to add a JS-functions like:
PolymerExpressions.prototype.timeofdate = function(input) {
if(input) {
return input.substring(11,16)
}
(Extracting hour:minute from "MongoDB-timestamp" like 2014-10-04T12:34:56+02:00)
And use it with piped variable like:
{{starts | timeofdate}}
When I tried to upgrade the code above to 0.9, I had to create this element instead:
<script>
Polymer({
is: 'x-substr',
properties: {
start: Number,
end: Number,
},
attached: function() {
this.innerHTML = this.innerHTML.substring(this.start, this.end);
}
});
</script>
And use it like this:
<x-substr start="11" end="16">{{starts}}</x-substr>
(Use "attached" callback instead of "ready", if you should use this element with any data binding)
Is this the "right way" to do filter functionality like above in Polymer 0.9+?
The closest you will get to the filter behaviour in 0.5 are computed bindings in 0.9+.
For your example this would be something like this:
<dom-module id="...">
<template>
...
<span>{{timeofdate(starts)}}</span>
...
</template>
<dom-module>
Polymer({
...
timeofdate: function (input) {
return input.substring(11,16);
}
...
});
If you need this time in more than one place you could also make it a computed property instead.
<dom-module id="...">
<template>
...
<span>{{starttime}}</span>
...
</template>
<dom-module>
Polymer({
...
properties: {
starts: String,
starttime: {
type: String,
computed: 'timeofdate(starts)'
}
},
timeofdate: function (input) {
return input.substring(11,16);
}
...
});
Hi i'd like to extend from a native HTML Element with Polymer for creating a custom web component.
My polymer ready-callback is getting called, when i'm not extending. As soon as i extend, nothing gets called anymore. Though the shadow DOM for the element is being created...
Here is my code for the usage:
<!DOCTYPE html>
<html>
<head>
<title>Custom Component Usage</title>
<script src="bower_components/platform/platform.js"></script>
<link rel="import" href="elements/extended-item.html">
</head>
<body>
<extended-item>I was extended from div!</extended-item>
</body>
</html>
Custom Element, which extends div:
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="extended-item" extends="div">
<template>
<content></content>
</template>
</polymer-element>
<script>
Polymer('extended-item',
{
created: function ()
{
console.log('EXTENDED ITEM IS CREATED!');
},
ready: function ()
{
console.log('EXTENDED ITEM IS READY!');
},
attached: function ()
{
console.log('EXTENDED ITEM IS ATTACHED!');
},
domReady: function ()
{
console.log('EXTENDED ITEMS DOM IS READY!');
},
detached: function ()
{
console.log('EXTENDED ITEM IS DETACHED!');
},
attributeChanged: function (attrName, oldVal, newVal)
{
//var newVal = this.getAttribute(attrName);
console.log(attrName, 'old: ' + oldVal, 'new:', newVal);
}
});
</script>
Any idea?
thanks in advance,
Rob
This works properly if, instead of referring to the element as <extended-item>, you instead use <div is="extended-item">.
Here's an example (jsbin):
<polymer-element name="extended-item" extends="div">
<template>
<p>This is part of the template.</p>
<content></content>
</template>
<script>
Polymer('extended-item', {
created: function() {
console.log('EXTENDED ITEM IS CREATED!');
},
ready: function() {
console.log('EXTENDED ITEM IS READY!');
},
attached: function() {
console.log('EXTENDED ITEM IS ATTACHED!');
},
domReady: function() {
console.log('EXTENDED ITEMS DOM IS READY!');
},
detached: function() {
console.log('EXTENDED ITEM IS DETACHED!');
},
attributeChanged: function (attrName, oldVal, newVal)
{
//var newVal = this.getAttribute(attrName);
console.log(attrName, 'old: ' + oldVal, 'new:', newVal);
}
});
</script>
</polymer-element>
<div is="extended-item">I was extended from div!</div>
EDIT: As pointed out in this comments, this is expected behavior, documented in the Custom Elements spec.