PolymerJS 1.0 : How to get properties of dynamically created component? - javascript

<dom-module id="element-1">
<template>
<input type="text" value={{title}}>
</template>
<script>
Polymer({
properties: {
title: {type: String}
}
})
</script>
</dom-module>
<dom-module id="element-2">
<template>
<element-1></element-1> // Added dynamically using javascript.
</template>
<script>
Polymer({
properties: {
property_1: {type:String}
},
// Here, I can access property_1 by this.property_1
// How to get the property of element-1(title) here?
})
</script>
</dom-module>
So, basically, I have a component (element-2). Inside that component I dynamically add another element (element-1). Now, how the I read the properties of element-1 from element-2?
Any help will be much appreciated.

Polymer has an instance method to query its local DOM:
$$(selector). Returns the first node in this element's local DOM that matches selector.
With this method, you could use this.$$('element-1').title from <element-2>.
<head>
<base href="https://polygit.org/polymer+1.5.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<element-2></element-2>
<dom-module id="element-1">
<template>
<span>{{title}}</span>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'element-1',
properties : {
title: {
type: String,
value: "Hello world!"
}
}
});
});
</script>
</dom-module>
<dom-module id="element-2">
<template>
<div id="container"></div>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'element-2',
addElement1: function() {
var e1 = document.createElement('element-1');
this.$.container.appendChild(e1);
},
ready: function() {
this.addElement1();
var e1ref = this.$$('element-1');
console.log("this.$$('element-1').title:", e1ref.title);
}
});
});
</script>
</dom-module>
</body>
codepen

Related

Selcting the first <content> element with polymer 1

I am using Polymer 1 for web-development and I am encountering a small lack of understanding. Imagine the following:
<div class="value">
<content></content>
</div>
I can easily style the content with the .value selector. Now I only want to style the First content element. :first-child etc. doesn't seem to work.
How can I select different elements of my <content></content> in Polymer?
Thanks!
Note that <content> has been deprecated for <slot>.
To target the first child of the <slot>/<content>, use ::slotted(:first-child):
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
properties: {
foo: {
type: String,
value: 'Hello world!'
}
}
});
});
<head>
<base href="https://cdn.rawgit.com/download/polymer-cdn/1.8.0/lib/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-foo>
<div>first</div>
<div>second</div>
<div>third</div>
</x-foo>
<dom-module id="x-foo">
<template>
<style>
::slotted(:first-child) {
color: red;
}
</style>
<slot></slot>
</template>
</dom-module>
</body>

Polymer Data Bind to a method

I am using a custom element that contains a <paper-dialog>, so that I can reuse the dialog style in my application.
The structure is the following:
Polymer({
is: 'dialog-confirm',
properties: {
title: {
type: String,
value: 'Dialog Title',
reflectsToAttribute: true
},
message: {
type: String,
value: 'Dialog message',
reflectsToAttribute: true
}
},
/**
* Triggered when the document is loaded
*/
ready: function () {
var me = this;
},
/**
* Open the dialog
*/
open: function () {
this.$.dialog.open();
}
});
Then, I declare my component as follows in order to have a "prepped" dialog ready to go:
(I removed the <link import="..."> for brevity)
<dom-module id="dialog-confirm">
<template>
<style>
</style>
<paper-dialog id="confirmation"
modal with-backdrop
entry-animation="slide-from-top-animation"
exit-animation="fade-out-animation"
on-iron-overlay-closed="_onSignoutConfirm">
<h2>{{title}}</h2>
<paper-dialog-scrollable>
<p>{{message}}</p>
</paper-dialog-scrollable>
<div class="buttons">
<paper-button class="normal" dialog-dismiss>NO</paper-button>
<paper-button class="positive" dialog-confirm>YES</paper-button>
</div>
</paper-dialog>
</template>
<script type="text/javascript" src="dialog-confirm.js"></script>
</dom-module>
The problem is that this is a component, and I would like to expose the iron-overlay-closed event outside the component. Otherwise, when I re-use my component, I can't data-bind this to a new method, as in:
<dialog-confirm id="myDialog" on-iron-overlay-closed="_myCustomMethod"></dialog-confirm>
Is this possible?
The iron-overlay-closed event already bubbles up from the child component, as seen in the following demo. If it doesn't bubble up for you, the problem might be caused by something else not shown in your question.
<head>
<base href="https://polygit.org/polymer+1.7.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-dialog/paper-dialog.html">
<link rel="import" href="paper-button/paper-button.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<x-dialog on-iron-overlay-closed="_myCustomMethod"></x-dialog>
</template>
<script>
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
_myCustomMethod: function() {
console.log('_myCustomMethod: overlay closed');
}
});
});
</script>
</dom-module>
<dom-module id="x-dialog">
<template>
<paper-dialog opened on-iron-overlay-closed="_onIronOverlayClosed">
<div class="buttons">
<paper-button dialog-dismiss>Ok</paper-button>
</div>
</paper-dialog>
</template>
<script>
HTMLImports.whenReady(() => {
Polymer({
is: 'x-dialog',
_onIronOverlayClosed: function() {
console.log('_onIronOverlayClosed: overlay closed');
}
});
});
</script>
</dom-module>
</body>
codepen

How to add dynamically extended element with Polymer?

I've got button:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/core-input/core-input.html">
<polymer-element name="count-button" extends="button" on-click="increment">
<template>
<content>Increment: </content>
</template>
<script>
Polymer({
counter: 0,
increment: function(e, detail, sender) {
this.counter++;
alert(this.counter);
}
})
</script>
</polymer-element>
I successfully use it in html by:
<button is="count-button"></button>
How to add such button in js? My incorrect version is (ready function):
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name='my-input'>
<template>
my input
<style>
</style>
</template>
<script>
Polymer('my-input', {
publish: {
},
ready: function() {
var node = document.createElement("button");
node.setAttribute('is', 'count-button');
this.shadowRoot.appendChild(node);
}
});
</script>
</polymer-element>
I've found the solution by my self and it's as easy as these 2 lines:
var node = document.createElement("button", 'count-button');
this.shadowRoot.appendChild(node);
So the complete answer is here:
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name='my-input'>
<template>
my input
<style>
</style>
</template>
<script>
Polymer('my-input', {
publish: {
},
ready: function() {
# only these 2 lines
var node = document.createElement("button", 'count-button');
this.shadowRoot.appendChild(node);
}
});
</script>
</polymer-element>

Polymer custom elements and Polymer-gestures

I would like to add listener event on a Polymer custom element with Polymer-gestures.
This is my sample code :
- my-custom-element.html
<link rel="import" href="../polymer/polymer.html">
<polymer-element name="my-custom-element" attributes="width height color">
<template>
<canvas id="canvas" width="{{width}}" height="{{height}}" style="background-color: {{color}}" touch-action="none"></canvas>
</template>
<script>
Polymer({
width: '',
height: '',
color: ''
});
</script>
</polymer-element>
- my-custom-parent-element.html
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../polymer-gestures/polymer-gestures.html">
<polymer-element name="my-custom-parent-element">
<template>
<my-custom-element width="300px" height="200px" color="yellow"></my-custom-element>
</template>
<script>
Polymer({
ready: function() {
this.myCustomElement = this.shadowRoot.querySelector('my-custom-element');
var events = [
// base events
'down',
'up',
'trackstart',
'track',
'trackend',
'tap',
'hold',
'holdpulse',
'release'
];
events.forEach(function(en) {
PolymerGestures.addEventListener(this.myCustomElement, en, function (inEvent) {
...
});
}
});
</script>
</polymer-element>
I have an error like this
Uncaught TypeError: Cannot read property '_pgListeners' of undefined
In debug mode when I add the event listener in my-custom-parent-element.html, I checked the value of the myCustomElement variable, and it's null.
How could I add the event listener on the myCustomElement variable ???
The querySelector in the following line is misspelled:
this.myCustomElement = this.shadowRoot.querrySelector('my-custom-element');
Try with this.shadowRoot.querySelector('my-custom-element');.

How to discuss between custom Polymer elements without events

I would like to discuss between custom elements without events in a parent custom element.
How could I do this, if it's possible ?
This is my-custom-parent-element.htlm :
<link rel="import" href="../my-custom-elment-1.html">
<link rel="import" href="../my-custom-elment-2.html">
<polymer-element name="my-custom-parent-element" noscript>
<template>
<my-custom-elment-1></my-custom-elment-1>
<my-custom-elment-2></my-custom-elment-2>
</template>
</polymer-element>
this is my-custom-element-1 :
<link rel="import" href="../polymer-gestures/polymer-gestures.html">
<polymer-element name="my-custom-element-1">
<template>
<div><canvas width="300px" height="200px"></canvas></div>
</template>
<script>
Polymer({
ready: function() {
<!-- Here, I need notify my-custom-element-2 that canvas received an event without re-send an event-->
}
});
</script>
</polymer-element>
this is my-custom-element-2 :
<polymer-element name="my-custom-element-2">
<template>
<div></div>
</template>
<script>
Polymer({
ready: function() {
<!-- Here, I need to change value by my-custom-element-1 notifications -->
}
});
</script>
</polymer-element>
Not sure either how you want to do this.
But you can also give reference to elem1 from the parent :
<polymer-element name="my-custom-parent-element" noscript>
<template>
<my-custom-elment-1 id="elem1"></my-custom-elment-1>
<my-custom-elment-2 id="elem2"></my-custom-elment-2>
</template>
<script>
Polymer({
domReady: function() {
this.$.elem1.target = this.$.elem2
}
});
</script>
</polymer-element>
And in elem1 :
<polymer-element name="my-custom-element-1" attributes="target">
<template>
<div><canvas width="300px" height="200px"></canvas></div>
</template>
<script>
Polymer({
ready: function() {
<!-- Here, I need notify my-custom-element-2 that canvas received an event without re-send an event-->
target.xxx();
}
});
</script>
</polymer-element>
But usually, the event way is better

Categories