paper-dialog handle onclose in component class - polymer

I'm trying to use the 'paper-dialog' tag for Polymer 2 in a web component.
I'm trying to detect when the user clicks the cancel button vs the save/ok button.
The documenation says to create an event for 'iron-overlay-closed' to detect when the OK/Save button is clicked.
My problem is that the 'iron-overlay-closed' is firing even when I click the cancel button.
From my reading of the documentation only the button with dialog-confirm attribute should cause the event to fire.
<paper-dialog modal backdrdop id="dialog">
<h2>Select Time</h2>
<paper-dialog-scrollable>
<div slot="body">
<p>Body is here</p>
</div>
</paper-dialog-scrollable>
<div id="dialog-buttons">
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button dialog-confirm autofocus>Save</paper-button>
</div>
</paper-dialog>
The below open method adds the listener.
The fireCallback method is then closed regardless of whether I click Save or Cancel.
open()
{
this.$.dialog.addEventListener('iron-overlay-closed', ()=> {this.fireCallback()});
this.$.dialog.open();
}
fireCallback()
{
console.log("closing");
}

If you define on-click method for both buttons explicitly, then you understand which button clicked ;
Demo
<div class="buttons">
<paper-button dialog-dismiss on-tap="_cancelled">Cancel</paper-button>
<paper-button dialog-confirm autofocus on-tap="_confirmed">OK</paper-button>
</div>
At script:
_cancelled(){
console.log('Cancelled');
}
_confirmed(){
console.log('Confirmed');
}
EDIT
As #Brett Sutton 'coment, on close of the paper-dialog, iron-overlay-closed event fired;
<paper-dialog id="scrolling" on-iron-overlay-closed="_myClosedFunction">
at script;
_myClosedFunction(c){
console.log('Closed as ', c.detail); // canceled: false, confirmed: true
}

#HakanC your example lead me to the answer.
The problem was that I was missing the import for:
<link href="../../../bower_components/iron-overlay-behavior/iron-overlay-behavior.html" rel="import">
Without the import my addEventListener was always firing but the 'confirmed' field in the details object that came back with the event was always false.
So my two problems were:
1) didn't realise I was missing an import
2) expected the event to only fire when I clicked save
- it fires for cancel and save and you need to check the 'confirmed' field to see which button was actually clicked.
So the final dialog was:
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/paper-dialog/paper-dialog.html">
<link href="../../../bower_components/iron-overlay-behavior/iron-overlay-behavior.html" rel="import">
<dom-module id="dialog-test">
<template>
<style include="shared-styles">
:host {
display: block;
margin: 5px;
height: 100%;
}
paper-dialog {
width: 100%;
margin: 0px;
}
#dialog-buttons {
display: flex;
justify-content: space-between;
}
</style>
<paper-dialog modal backdrdop id="dialog">
<h2>Select Time</h2>
<paper-dialog-scrollable>
<div slot="body">
<p>Body is here</p>
</div>
</paper-dialog-scrollable>
<div id="dialog-buttons">
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button dialog-confirm autofocus>Save</paper-button>
</div>
</paper-dialog>
</template>
<script>
class DialogTest extends Polymer.Element {
static get is() {
return 'dialog-test';
}
static get properties() {
return {
};
}
open()
{
this.$.dialog.addEventListener('iron-overlay-closed', (e)=> {this.fireCallback(e)});
this.$.dialog.open();
}
fireCallback(e)
{
console.log(e.detail);
if (c.detail.confirmed == true)
{
console.log("saving")
}
}
connectedCallback()
{
super.connectedCallback();
this.open();
}
}
customElements.define(DialogTest.is, DialogTest);
</script> </dom-module>

Related

Polymer - How to remove an item from iron-list?

This live snippet builds a web-component which uses iron-list. Each item in the list has a delete button which, on click, removes the item from the list.
When an item is removed, all the next items shift up, but the last item displayed stays rather than disapear as it should be.
According to this stackoverflow, simply by firing the event resize on the iron-list should be enough. But in my snippet, this doesn't help. Nether the iron-resize or the notifyResize function from the official iron-list documentation.
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="https://polygit.org/components/polymer/polymer-element.html">
<link rel="import" href="https://polygit.org/components/iron-list/iron-list.html">
<link rel="import" href="https://polygit.org/components/paper-button/paper-button.html">
<dom-module id="my-list">
<template>
<iron-list id="list" items="{{items}}">
<template>
<div style="display:flex; justify-content: space-between; align-items: center;">
<div style="margin: 20px; ">
{{item}}
</div>
<paper-button on-tap="_onDeleteClicked"
style="background: red; color: white;">Remove</paper-button>
</div>
</template>
</iron-list>
</template>
<script>
class MyList extends Polymer.Element {
static get is() { return "my-list"; }
// set this element's employees property
constructor() {
super();
this.items = [1,2,3,4];
}
_onDeleteClicked(event){
this.splice("items", event.model.index, 1);
// ---- any resize call doesn't help a thin ---
this.$.list.fire('iron-resize');
this.$.list.fire('resize');
this.$.list.notifyResize();
}
}
customElements.define(MyList.is, MyList);
</script>
</dom-module>
<my-list></my-list>
You may find an "hidden" attribute on the last item. As items are reused by iron-list when scrolling the item does not get removed. This CSS rule should hide it away
#list [hidden] { display: none; }
"It's simple! The css display property of the root element, in the iron-list's template, must not be set. Then just wrap your flexbox in another simple div."
Here's the live snippet solved:
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="https://polygit.org/components/polymer/polymer-element.html">
<link rel="import" href="https://polygit.org/components/iron-list/iron-list.html">
<link rel="import" href="https://polygit.org/components/paper-button/paper-button.html">
<dom-module id="my-list">
<template>
<iron-list id="list" items="{{items}}">
<template>
<!--YOU MUST NO CHANGE THE CSS DISPLAY PROPERTY OF THE ROOT ELEMENT OF THE TEMPLATE!-->
<div>
<div style="display:flex; justify-content: space-between; align-items: center;">
<div style="margin: 20px; ">
{{item}}
</div>
<paper-button on-tap="_onDeleteClicked"
style="background: red; color: white;">Remove</paper-button>
</div>
</div>
</template>
</iron-list>
</template>
<script>
class MyList extends Polymer.Element {
static get is() { return "my-list"; }
// set this element's employees property
constructor() {
super();
this.items = [1,2,3,4];
}
_onDeleteClicked(event){
this.splice("items", event.model.index, 1);
this.$.list.notifyResize();
}
}
customElements.define(MyList.is, MyList);
</script>
</dom-module>
<my-list></my-list>

Polymer and app-storage: Remove entry button

I ran into a problem with polymer and app-storage when trying to remove an entry.
I'm trying to add a button to the Vaading Grid that will delete the entry on which the button is set.
The only thing is that I cannot seem to make it work, when I click the button, even console.log doesn't work. What am I doing wrong here?
Here is the code:
<!--
#license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="shared-styles.html">
<link rel="import" href="../bower_components/vaadin-grid/vaadin-grid.html">
<link rel="import" href="../bower_components/vaadin-date-picker/vaadin-date-picker.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/app-storage/app-localstorage/app-localstorage-document.html">
<dom-module id="my-view1">
<template>
<style include="shared-styles">
:host {
display: block;
padding: 10px;
}
.form {
display: flex;
flex-direction: column;
}
.form paper-input {
flex: 1;
margin-right: 10px;
}
.form vaadin-date-picker {
flex: 1;
margin-top: 10px;
}
.form paper-button {
margin-top: 10px;
align-self: flex-end;
}
</style>
<div class="card">
<div class="form">
<paper-input label="Sum" value="{{todo.task}}" auto-validate placeholder="Suma" required=true pattern="[0-9]*" error-message="Numbers only"></paper-input>
<vaadin-date-picker label="When" value="{{todo.due}}"></vaadin-date-picker>
<paper-button raised on-tap="_addToDo">Add</paper-button>
</div>
<br>
<vaadin-grid items={{todos}}>
<vaadin-grid-column width="calc(50% - 100px)">
<template class="header">Sum</template>
<template>{{item.task}}</template>
</vaadin-grid-column>
<vaadin-grid-column width="calc(50% - 100px)">
<template class="header">When</template>
<template>{{item.due}}</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template>
<div style="display: flex; justify-content: flex-end;">
<button on-tap="_remove">Remove</button>
</div>
</template>
</vaadin-grid-column>
</vaadin-grid>
</div>
<app-localstorage-document key="todos" data="{{todos}}">
</app-localstorage-document>
</template>
<script>
class MyView1 extends Polymer.Element {
static get is() { return 'my-view1'; }
static get properties() {
return {
todo: {
type: Object,
value: () => { return {} }
},
todos: {
type: Array,
value: () => []
}
};
}
_addToDo() {
this.push('todos', this.todo);
this.todo = {};
};
_remove() {
console.log("Clicked!");
};
}
window.customElements.define(MyView1.is, MyView1);
</script>
</dom-module>
So the _addToDo button is working, but not the _remove button. When I open the console, this is empty.
Please let me know what am I doing wrong here. Thank you!
Since button is native HTML Element on-tap will not work.
Change it to polymer element like paper-button or change on-tap to onclick.

Polymer's paper-dialog not working can't be opened

I am trying to implement a paper-dialog box that will reveal itself when a paper-fab is tapped in the image below:
my app's main screen
but I can't get the paper-dialog to open.
I have implemented paper-dialog into my app as following:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/polymerfire/firebase-query.html">
<link rel="import" href="../bower_components/paper-fab/paper-fab.html">
<link rel="import" href="../bower_components/paper-dialog/paper-dialog.html">
<link rel="import" href="../bower_components/polymerfire/firebase-auth.html">
<link rel="import" href="shared-styles.html">
<dom-module id="my-view1">
<template>
<style include="shared-styles">
:host {
display: block;
padding: 10px;
}
paper-fab{
position:fixed;
right:20px;
bottom:68px;
--paper-fab-keyboard-focus-background:--accent-color;
}
</style>
<firebase-auth
id="auth"
user="{{user}}"
provider=""
status-known="{{statusKnown}}"
on-error="handleError">
</firebase-auth>
<firebase-query
id="query"
path="/posts"
data="{{posts}}">
</firebase-query>
<div class="card">
<h1>Post</h1>
<ul id="post-list">
<template is="dom-repeat" items="[[posts]]" as="post">
<li>
<p class="content">[[post.body]]</p>
</li>
</template>
</ul>
</div>
<paper-fab icon="add" onclick="dialog.open()"></paper-fab>
<paper-dialog id="dialog">
<paper-textarea id="post" label="Write your post here..."></paper-textarea>
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button on-tap="post" id="btnPost" raised class="indigo" hidden$="[[!user]]">Post</paper-button>
</paper-dialog>
</template>
<script>
Polymer({
is: 'my-view1',
properties:{
user:{
type: Object
},
statusKnown:{
type: Object
},
posts: {
type: Object
}
},
post: function() {
this.$.query.ref.push({
"Uid": this.user.uid,
"body": this.$.post.value
});
this.$.post.value = null;
}
});
</script>
</dom-module>
<paper-fab icon="add" onclick="dialog.open()"></paper-fab>
<paper-dialog id="dialog">
<paper-textarea id="post" label="Write your post here..."></paper-textarea>
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button on-tap="post" id="btnPost" raised class="indigo" hidden$="[[!user]]">Post</paper-button>
</paper-dialog>
This snippet here are taken from the demo on this page:
https://www.webcomponents.org/element/PolymerElements/paper-dialog/v1.1.0/demo/demo/index.html
but when I actually tap on the paper-fab, I get the following error:
Uncaught ReferenceError: dialog is not defined
at HTMLElement.onclick (view3:1)
onclick # view3:1
Does anyone have any idea how I can make the paper-dialog open when the paper-fab is tapped? I suppose I am missing some includes, but I cannot figure out which one.
at first, don't use onclick. There are Polymer event attributes like on-click or on-tap. Second, you should call function which will open the selected dialog
Example:
<paper-fab icon="add" on-tap="_openDialog"></paper-fab>
and inside script
_openDialog: function() {
this.$.dialog.open();
}
this.$.dialog find element with id dialog and call function open

How to access details of a swiped paper-card in iron-swipeable-container

I have a swipeable-container with a dom-repeat (firebase data)
<iron-swipeable-container id="teamchat">
<template is="dom-repeat" items="[[tcmmessages]]" as="tcmmessage">
<paper-card id="tcmcard" class="swipe item blue" data-index$="[[tcmmessage.__firebaseKey__]]">
<div class="card-content">
<b>[[tcmmessage.teamname]]</b>
<paper-icon-button style="color: red;" on-tap="_startChat" icon="communication:chat"></paper-icon-button><br>
[[tcmmessage.beitrag]]<br>
<span class="chatmetadata">von [[tcmmessage.username]]
• [[tcmmessage.update]] • [[tcmmessage.uptime]] </span>
</div>
</paper-card>
</template>
</iron-swipeable-container>
I defined a listener
listeners: {
'teamchat.iron-swipe': '_onTeamChatSwipe'
},
I try to access data-index from the swiped paper-card.
_onTeamChatSwipe: function() {
var card = this.$$('#tcmcard');
var key = card.getAttribute("data-index");
but after swipe event I can not access data-index of the swiped card.
With this.$$('#tcmcard') in the iron-swipe handler, you're querying the local DOM for the swiped element, but it's removed from the DOM before the iron-swipe event fires, so the query would not return what you'd expect.
But you don't need to query for the swiped element because <iron-swipeable-container> fires the iron-swipe event with the swiped element stored in event.detail.target.
Try this:
_onTeamChatSwipe: function(e) {
var card = e.detail.target;
var key = card.getAttribute("data-index");
// simpler syntax to get `data-index`
// key = card.dataset.index;
}
<head>
<base href="https://polygit.org/polymer+1.4.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-card/paper-card.html">
<link rel="import" href="iron-swipeable-container/iron-swipeable-container.html">
<link rel="import" href="iron-flex-layout/iron-flex-layout-classes.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<style include="iron-flex">
paper-card {
margin-bottom: 16px;
}
</style>
<template>
<iron-swipeable-container class="container" on-iron-swipe="_onSwipe">
<template is="dom-repeat" items="[[items]]">
<paper-card heading="{{item}}" data-index$="{{index}}" class="layout vertical">
<div class="card-content">
Swipe me left or right
</div>
</paper-card>
</template>
</iron-swipeable-container>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
properties : {
items: {
type: Array,
value: function() {
return [1,2,3];
}
}
},
_onSwipe: function(e) {
var card = e.detail.target;
console.log(card.getAttribute('data-index'));
// simpler syntax to get 'data-index'
console.log(card.dataset.index);
}
});
});
</script>
</dom-module>
</body>
codepen

How can I "refresh" iron-swipeable-container after a change of data in firebase

My code with swipable-container and dom-repeat of firebase-data
<iron-swipeable-container id="teamchat">
<paper-card class="swipe item blue">
<template is="dom-repeat" items="[[tcmmessages]]" as="tcmmessage">
<div class="card-content">
<b>[[tcmmessage.teamname]]</b><br>
[[tcmmessage.beitrag]]<br>
<span class="chatmetadata">von [[tcmmessage.username]]
• [[tcmmessage.update]] • [[tcmmessage.uptime]] </span>
</div>
</template>
</paper-card>
</iron-swipeable-container>
I have defined a listener
listeners: {
'teamchat.iron-swipe': '_onTeamChatSwipe'
},
and remove the firebase-data with '_onTeamChatSwipe'.
That work fine!
But when there is new firebase-data, how can I bring the iron-swipeable-container back again without refreshing the entire page? I don't find a solution.
It looks like you've created just one paper-card that contains multiple messages. When the card is swiped away, your code has no template to refill the container.
Did you actually mean to create a card for each message? That would require moving paper-card inside the template repeater like this:
<iron-swipeable-container id="teamchat">
<template is="dom-repeat" items="[[tcmmessages]]" as="tcmmessage">
<paper-card class="swipe item blue">
<div class="card-content">
<b>[[tcmmessage.teamname]]</b><br>
[[tcmmessage.beitrag]]<br>
<span class="chatmetadata">von [[tcmmessage.username]]
• [[tcmmessage.update]] • [[tcmmessage.uptime]] </span>
</div>
</paper-card>
</template>
</iron-swipeable-container>
When tcmmessages refills (via Firebase), the iron-swipeable-container automatically repopulates with a paper-card per message.
Here's a demo of similar code that shows that behavior:
<head>
<base href="https://polygit.org/polymer+1.4.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-card/paper-card.html">
<link rel="import" href="iron-swipeable-container/iron-swipeable-container.html">
<link rel="import" href="iron-flex-layout/iron-flex-layout-classes.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<style include="iron-flex">
paper-card {
margin-bottom: 16px;
}
</style>
<template>
<iron-swipeable-container class="container">
<template is="dom-repeat" items="[[items]]">
<paper-card heading="{{item}}" class="layout vertical">
<div class="card-content">
Swipe me left or right
</div>
</paper-card>
</template>
</iron-swipeable-container>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
properties : {
items: {
type: Array,
value: function() {
return [1,2,3];
}
}
},
_clearListAfterDelay: function(delay) {
this.async(function() {
this.set('items', []);
}, delay);
},
_refillListAfterDelay: function(delay) {
this.async(function() {
this.push('items', 4);
this.push('items', 5);
}, delay);
},
ready: function() {
this._clearListAfterDelay(1000);
this._refillListAfterDelay(2000);
}
});
});
</script>
</dom-module>
</body>
codepen