Polymer 1.0 Child element not firing to parent - polymer

I'm having trouble trying to fire an event from a child element to its parent on Polymer 1.0, and I can't see what am I doing wrong.
EDITED: Add more code
Child's code:
<link rel="import" href="../components/polymer/polymer.html" />
<link rel="import" href="../components/iron-input/iron-input.html" />
<link rel="import" href="../components/iron-icon/iron-icon.html" />
<link rel="import" href="../components/paper-input/paper-input container.html" />
<link rel="import" href="../components/paper-input/paper-input-error.html" />
<link rel="import" href="../components/iron-input/iron-input.html" />
<link rel="import" href="custom-table.html" />
<dom-module id="master-admin">
<style is="custom-style">
[...]
</style>
<template>
<custom-table selectable collist="{{columns}}" data="{{data}}">
</custom-table>
<div id="newrow" class="horizontal layout" hidden>
<template is="dom-repeat" items="{{columns}}" as="col">
<paper-input-container class="container flex">
<label class="label">{{col.name}}</label>
<input class="input" id="input" is="iron-input">
</paper-input-container>
</template>
</div>
<div id="iconsdiv" class="horizontal layout">
<iron-icon id="adicon" icon="add-circle" on-click="addrow"></iron-icon>
<div class="flex"></div>
<iron-icon id="delicon" icon="cancel" on-click="delrow"></iron-icon>
<iron-icon id="edicon" icon="create" on-click="editrow"></iron-icon>
</div>
</template>
<script>
Polymer({
is: 'master-admin',
properties: {
doctype: String,
columns: Array,
data: Array
},
datachanged: function () {
debugger;
var updatedata = {
data: this.data,
doctype: this.doctype
};
this.fire('data-updated', updatedata);
},
addrow: function (e) {
[...]
this.datachanged();
},
delrow: function (e) {
[...]
this.datachanged();
},
editrow: function (e) {
[...]
this.datachanged();
}
});
</script>
</dom-module>
On parent:
<master-admin
doctype="{{master.DocumentalTypeId}}"
columns="{{master.Columns}}"
data="{{master.Data}}"
on-data-updated="masterupdated">
</master-admin>
masterupdated: function () {
alert('updated master!');
}
Just to be clear, datachanged works just fine and it's called when it should. masterupdated on the parent does not.
The alert is never firing, nor the code gives any error. I guess is just something with Polymer 1.0 that works different.

The basic setup you describe does work, there must be a problem in the details somewhere. Here is an example:
<!doctype html>
<head>
<meta charset="utf-8">
<base href="http://milestech.net/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<style>
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<x-parent></x-parent>
<hr>
<dom-module id="master-admin">
<template>
<button on-tap="updateData">Update Data</button>
</template>
<script>
// only need this when both (1) in the main document and (2) on non-Chrome browsers
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'master-admin',
updateData: function() {
this.fire('data-updated');
}
});
});
</script>
</dom-module>
<dom-module id="x-parent">
<style>
</style>
<template>
<master-admin on-data-updated="masterupdated"></master-admin>
</template>
<script>
// only need this when both (1) in the main document and (2) on non-Chrome browsers
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-parent',
masterupdated: function() {
document.body.appendChild(this.create('h3', {textContent: 'data-updated!'}));
}
});
});
</script>
</dom-module>
</body>

Can you try this?
<template is="dom-bind" id="t">
<master-admin
doctype="{{master.DocumentalTypeId}}"
columns="{{master.Columns}}"
data="{{master.Data}}"
on-data-updated="masterupdated">
</master-admin>
</template>
<script>
var template = document.querySelector('#t');
template.masterupdated= function () {
consloe.log("MASTER UPDATED!!");
};
</script>

Related

Polymer App-Route Example in jsBin

Can anyone show using jsBin an example of how to use app-route?
https://jsbin.com/retokid/edit?html,output
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
<title>Polymer</title>
<script src="https://polygit.org/app-route+polymerelements+*/components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/polymer/polymer.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/paper-input/paper-input.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/paper-button/paper-button.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/app-route/app-route.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/app-route/app-location.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/iron-pages/iron-pages.html">
</head>
<body>
<x-shell></x-shell>
<dom-module id="x-a">
<template>
<h2>page A</h2>
<paper-input value="{{email}}" placeholder="set email"></paper-input>
<paper-input value="{{phone}}" placeholder="set phone"></paper-input>
<paper-button on-click="_submit">submit</paper-button>
</template>
<script>
// NOTE: not needed if we declare this element in a separate file and import it.
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-a',
properties: {
email: {
type: String
}
},
_submit: function() {
this.fire('info-updated', {
email: this.email,
phone: this.phone
});
}
});
});
</script>
</dom-module>
<dom-module id="x-b">
<template>
<h2>page B</h2>
<div>
email: [[userInfo.email]]
</div>
</template>
<script>
// NOTE: not needed if we declare this element in a separate file and import it.
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-b',
properties: {
email: {
type: String
}
}
});
});
</script>
</dom-module>
<dom-module id="x-shell">
<template>
<app-location route="{{route}}" use-hash-as-path></app-location>
<app-route
route="{{route}}"
pattern="/:page"
data="{{routeData}}"
tail="{{subroute}}"></app-route>
<iron-selector selected="{{routeData.page}}" attr-for-selected="name" role="navigation">
<a name="x-a" href="#/x-a">x-a</a>
<a name="x-b" href="#/x-b">x-b</a>
</iron-selector>
<iron-pages selected="[[routeData.page]]" attr-for-selected="name">
<x-a name="x-a" route="{{route}}" user-info="[[userInfo]]" on-info-updated="_updateInfo"></x-a>
<x-b name="x-b" route="{{route}}" user-info="[[userInfo]]"></x-b>
</iron-pages>
</template>
<script>
// NOTE: not needed if we declare this element in a separate file and import it.
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-shell',
properties: {
userInfo: {
type: Object,
value: function() {
return {};
}
},
page: {
type: String,
reflectToAttribute: true
}
},
_updateInfo: function(event) {
console.log('infoUpdated', event.detail);
this.set('userInfo', event.detail);
}
});
});
</script>
</dom-module>
</body>
</html>
This is your worked example, check it please.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
<title>Polymer</title>
<script src="https://polygit.org/app-route+polymerelements+*/components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/polymer/polymer.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/paper-input/paper-input.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/paper-button/paper-button.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/app-route/app-route.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/app-route/app-location.html">
<link rel="import" href="https://polygit.org/app-route+polymerelements+*/components/iron-pages/iron-pages.html">
</head>
<body>
<x-shell></x-shell>
<dom-module is="x-a">
<template>
<h2>page A</h2>
<paper-input value="{{email}}" placeholder="set email"></paper-input>
<paper-input value="{{phone}}" placeholder="set phone"></paper-input>
<paper-button on-tap="_submit">submit</paper-button>
</template>
<script>
// NOTE: not needed if we declare this element in a separate file and import it.
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-a',
properties: {
email: {
type: String
}
},
_submit: function() {
this.fire('info-updated', {
email: this.email,
phone: this.phone
});
}
});
});
</script>
</dom-module>
<dom-module is="x-b">
<template>
<h2>page B</h2>
<div>
email: [[userInfo.email]]
</div>
</template>
<script>
// NOTE: not needed if we declare this element in a separate file and import it.
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-b',
properties: {
userInfo: {
type: Object
}
}
});
});
</script>
</dom-module>
<dom-module is="x-shell">
<template>
<app-location route="{{route}}" use-hash-as-path></app-location>
<app-route
route="{{route}}"
pattern="/:page"
data="{{routeData}}"
tail="{{subroute}}"></app-route>
<iron-selector selected="{{routeData.page}}" attr-for-selected="name" role="navigation">
<a name="x-a" href="#/x-a">x-a</a>
<a name="x-b" href="#/x-b">x-b</a>
</iron-selector>
<iron-pages selected="[[routeData.page]]" attr-for-selected="name">
<x-a name="x-a" route="{{route}}" user-info="[[userInfo]]" on-info-updated="_updateInfo"></x-a>
<x-b name="x-b" route="{{route}}" user-info="[[userInfo]]"></x-b>
</iron-pages>
</template>
<script>
// NOTE: not needed if we declare this element in a separate file and import it.
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-shell',
properties: {
userInfo: {
type: Object,
value: function() {
return {};
}
},
page: {
type: String,
reflectToAttribute: true
}
},
_updateInfo: function(event) {
console.log('infoUpdated', event.detail);
this.set('userInfo', event.detail);
}
});
});
</script>
</dom-module>
</body>
</html>

Getting Child Element From Polymer.dom(event)

What is the best way to grab a hold of the element paper-ripple to attach a event listener for the animation end event? This element will be in a dom repeat. I tried getting children from Polymer.dom(event).localTarget; but had no success. The on-tap needs to stay in the parent.
<div on-tap="goToSingleListing" data-listingID="[[url.listing_id]]">
<paper-ripple></paper-ripple>
...
goToSingleListing: function(event) {
var el = Polymer.dom(event).localTarget;
var firstChildElementName = Polymer.dom(el).firstChild;
...
firstChildElementName.addEventListener('transitionend', ()=> {
page(url);
});
Instead of trying to get a reference to the <paper-ripple> from your tap event handler, you could use an annotated event listener directly on the <paper-ripple> for its transitionend event.
// dom-module template
<template is="dom-repeat" items="[[items]]">
<div on-tap="...">
<paper-ripple on-transitionend="_onItemTransitionEnd"></paper-ripple>
</div>
</template>
// dom-module script
Polymer({
...
_onItemTransitionEnd: function(e) {
...
}
}
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
_onItemTap: function(e) {
console.log('tap', e.model.index);
},
_onItemTransitionEnd: function(e) {
console.log('transitionend', e.model.index);
}
});
});
<head>
<base href="https://polygit.org/polymer+1.7.1/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-ripple/paper-ripple.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<template is="dom-repeat" items="[1,2,3,4]">
<div on-tap="_onItemTap">
<h2>Item [[item]]</h2>
<paper-ripple on-transitionend="_onItemTransitionEnd"></paper-ripple>
</div>
</template>
</template>
</dom-module>
</body>
codepen

Polymer 1.x: Imperatively accessing DOM nodes inside a dom-if template

Here is my jsBin.
I want to access by its id a DOM node inside a dom-if template. With my existing code, I expect to see true when attempting to cast these nodes to Booleans, but instead I get false (i.e., undefined).
Steps to recreate the problem:
Open this jsBin.
Understand that the HTML pane on the right is working correctly by showing Foo and Bar and not showing Baz.
Observe the console and understand the id="foo" node is accessible but the id="bar" and id="baz" elements are not. And this is my problem.
How can I access those nodes imperatively?
http://jsbin.com/kemoravote/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-form/iron-form.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<div id="foo">Foo</div>
<template is="dom-if" if="{{show}}">
<div id="bar">Bar</div>
</template>
<template is="dom-if" if="{{!show}}">
<div id="baz">Baz</div>
</template>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
show: {
type: Boolean,
value: function() {
return true;
}
}
},
attached: function() {
console.log('foo', !!this.$.foo);
console.log('bar', !!this.$.bar);
console.log('baz', !!this.$.baz);
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
The $ selector won't work. You have to use $$ as follows:
console.log('baz', !!this.$$('#baz'));
Here is the jsBin.
http://jsbin.com/xogediyato/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-form/iron-form.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<div id="foo">Foo</div>
<template is="dom-if" if="{{show}}">
<div id="bar">Bar</div>
</template>
<template is="dom-if" if="{{!show}}">
<div id="baz">Baz</div>
</template>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
show: {
type: Boolean,
value: function() {
return true;
}
}
},
attached: function() {
console.log('foo', !!this.$.foo);
console.log('bar', !!this.$.bar);
console.log('baz', !!this.$.baz);
console.log('bar', !!this.$$('#bar'));
console.log('baz', !!this.$$('#baz'));
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>

Polymer 1.x: Two-way databinding for paper-dropdown-menu

I want to set the paper-dropdown-menu to the value of 'Three' upon loading. I want to do this by data binding the value attribute of the paper-dropdown-menu to a sub property of the element called item.number which is set when registering the element. When I attempt this using the below code, the result I see is that the paper-dropdown-menu displayed value is just blank instead of reading 'Three'.
What code changes will achieve my desired behavior?
Follow these steps to reproduce the problem.
Open this JSBin.
Note the content of the display value of the dropdown menu is blank.
Click the button labeled Click to show item
Observe the console prints:
[object Object] {
number: "Three"
}
Understand the above steps demonstrate my desired behavior is not occurring.
Select the number "Four" in the dropdown menu.
Click the button labeled Click to show item
Observe the console prints:
[object Object] {
number: "Four"
}
Understand the above step shows one-way data binding is working on the element.
How can I achieve my desired behavior?
http://jsbin.com/loceqayezo/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-dropdown-menu/paper-dropdown-menu.html" rel="import">
<link href="paper-listbox/paper-listbox.html" rel="import">
<link href="paper-item/paper-item.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<p>
<button on-tap="show">Click to show item</button>
</p>
<paper-dropdown-menu label="Numbers"
value="{{item.number}}">
<paper-listbox class="dropdown-content">
<paper-item>One</paper-item>
<paper-item>Two</paper-item>
<paper-item>Three</paper-item>
<paper-item>Four</paper-item>
</paper-listbox>
</paper-dropdown-menu>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
item: {
type: Object,
notify: true,
value: function() {
return {number: "Three"};
},
},
},
show: function() {
console.log('item', this.item);
},
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
Your code doesn't work because value property of <paper-dropdown-menu> is read-only. See the documentation.
Instead you can bind to <paper-listbox selected>. With minimal changes you will have to bind to dropdown's element index.
Polymer({
is: "x-element",
properties: {
item: {
type: Object,
notify: true,
value: function() {
return {number: 2};
},
},
},
show: function() {
console.log('item', this.item);
},
});
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-dropdown-menu/paper-dropdown-menu.html" rel="import">
<link href="paper-listbox/paper-listbox.html" rel="import">
<link href="paper-item/paper-item.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<p>
<button on-tap="show">Click to show item</button>
</p>
<paper-dropdown-menu label="Numbers">
<paper-listbox class="dropdown-content"
selected="{{item.number}}">
<paper-item>One</paper-item>
<paper-item>Two</paper-item>
<paper-item>Three</paper-item>
<paper-item>Four</paper-item>
</paper-listbox>
</paper-dropdown-menu>
</template>
</dom-module>
<x-element></x-element>
</body>
To keep the full name in your item you can add an attribute to you selectable elements and use the attrForSelected property of paper-listbox.
Polymer({
is: "x-element",
properties: {
item: {
type: Object,
notify: true,
value: function() {
return {number: "Three"};
},
},
},
show: function() {
console.log('item', this.item);
},
});
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-dropdown-menu/paper-dropdown-menu.html" rel="import">
<link href="paper-listbox/paper-listbox.html" rel="import">
<link href="paper-item/paper-item.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<p>
<button on-tap="show">Click to show item</button>
</p>
<paper-dropdown-menu label="Numbers">
<paper-listbox class="dropdown-content"
selected="{{item.number}}"
attr-for-selected="data-item">
<paper-item data-item="One">One</paper-item>
<paper-item data-item="Two">Two</paper-item>
<paper-item data-item="Three">Three</paper-item>
<paper-item data-item="Four">Four</paper-item>
</paper-listbox>
</paper-dropdown-menu>
</template>
</dom-module>
<x-element></x-element>
</body>

Using withBackdrop for paper-dialog prevents controls from being focused via tabbing

I have a paper-dialog that uses the with-backdrop property. I've noticed that after clicking anywhere within a paper-dialog that does not use the with-backdrop property, I can hit the tab key and the browser will focus the input element:
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-example',
ready: function() {
this.$$('paper-dialog').open();
}
});
});
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="paper-dialog/paper-dialog.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<link href="polymer/polymer.html" rel="import">
<dom-module id="x-example">
<style>
:host {
display: block;
}
</style>
<template>
<paper-dialog>
<h2 class="header">Hello</h2>
<paper-input
label="Focusable input"
tabindex
type="text">
</paper-input>
</paper-dialog>
</template>
</dom-module>
<x-example></x-example>
If I set the with-backdrop property, however, the browser will not focus the input element:
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-example',
ready: function() {
this.$$('paper-dialog').open();
}
});
});
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="paper-dialog/paper-dialog.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<link href="polymer/polymer.html" rel="import">
<dom-module id="x-example">
<style>
:host {
display: block;
}
</style>
<template>
<paper-dialog with-backdrop>
<h2 class="header">Hello</h2>
<paper-input
label="Focusable input"
tabindex
type="text">
</paper-input>
</paper-dialog>
</template>
</dom-module>
<x-example></x-example>
Is there a way to have a backdrop and still allow the dialog to navigatable via the keyboard?
Device info: I am experiencing this issue running Chrome v50 on OSX.
Seems to be issue with versions that you are using. I tried it on Polymer's website and my local and this seems to be working fine. Below are the versions that i used:
Paper-dialog: 1.0.4
Polymer: 1.3.2
Paper-input: 1.0.18
I'll also recommend you to open up an issue on Github for the same
In the demo, I included the tabindex attribute in my input element without specifying a value. Removing this property allowed the input to be focused:
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-example',
ready: function() {
this.$$('paper-dialog').open();
}
});
});
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="paper-dialog/paper-dialog.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<link href="polymer/polymer.html" rel="import">
<dom-module id="x-example">
<style>
:host {
display: block;
}
</style>
<template>
<paper-dialog with-backdrop>
<h2 class="header">Hello</h2>
<paper-input
label="Focusable input"
type="text">
</paper-input>
</paper-dialog>
</template>
</dom-module>
<x-example></x-example>