In the polymer dialog demo they have code like this:
<script src=
https://github.com/webcomponents/webcomponentsjs/blob/master/webcomponents.js>
<link rel="import" href="https://github.com/Polymer/polymer/blob/master/polymer.html">
<link rel="import" href="https://github.com/PolymerElements/paper-button/blob/master/paper-button.html">
<link rel="import" href="https://github.com/PolymerElements/paper-dialog/blob/master/paper-dialog.html">
<section onclick="clickHandler(event)">
<h4>Transitions</h4>
<paper-button data-dialog="animated">transitions</paper-button>
<paper-dialog id="animated" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop>
<h2>Dialog Title</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</paper-dialog>
</section>
<script>
function clickHandler(e) {
var button = e.target;
while (!button.hasAttribute('data-dialog') && button !== document.body) {
button = button.parentElement;
}
if (!button.hasAttribute('data-dialog')) {
return;
}
var id = button.getAttribute('data-dialog');
var dialog = document.getElementById(id);
if (dialog) {
dialog.open();
}
}
</script>
I want to wrap the button (or fab in my case) and the dialog into my own seperate web components.
I created a dialog-button that tried to wrap the button and the event:
<paper-fab class="addbutton" icon="add" onclick="clickHandler(event)"></paper-fab>
</template>
<script>
Polymer({
is: 'my-dialog-button',
properties: {
dialog_id: {
type: String
},
}
})
function clickHandler(e) {
var button = e.target;
while (!button.hasAttribute('dialog_id') && button !== document.body) {
button = button.parentElement;
}
if (!button.hasAttribute('dialog_id')) {
console.log("you have no element with 'dialog_id' defined")
return;
}
var id = button.getAttribute('dialog_id');
console.log("dialog " + id + " requested")
var dialog = document.getElementById(id);
if (dialog) {
dialog.open();
} else {
console.log("dialog " + id + " does not exist")
}
}
</script>
which allows me the following to work:
<thor-dialog-button dialog_id="add-button"></thor-dialog-button>
<paper-dialog id="add-button">
<h2>"Hello"</h2>
<p>"World"</p>
</paper-dialog>
However as soon as I wrap the dialog in its own component, the "id" is no longer available in that dom context. So it doesn't work.
I was thinking the ID approach doesnt really work and I need to bind the dialog "open" to the button "onclick" but I have no idea how to do that, I have found:
https://www.polymer-project.org/1.0/docs/devguide/templates.html
But i am not sure how to apply this to wrapped elements (or at least I have spectacularly failed on that approach so far).
In summary, what is the correct way to separate 2 wrapped web components and what would it look like?
You want to have two elements my-dialog-button
and my-dialog
. Your button element needs some re-work. We need to move the clickHandler
function inside the Polymer({ })
block. It is also recommended to use the on-tap
event instead of the on-click
. on-tap
achives more consistent experience on desktop and mobile.
<script>
Polymer({
is: 'my-dialog-button',
properties: {
dialogId: {
type: String
}
},
clickHandler: function (e) {
var button = e.target;
while (!button.hasAttribute('dialogId') && button !== document.body) {
button = button.parentElement;
}
if (!button.hasAttribute('dialogId')) {
console.log("you have no element with 'dialogId' defined");
return;
}
var id = button.getAttribute('dialogId');
console.log("dialog " + id + " requested");
var dialog = document.getElementById(id);
if (dialog) {
dialog.open();
}
else
{
console.log("dialog " + id + " does not exist")
}
}
});
Like that. One of the main things in polymer is to keep all of the javascript inside the Polymer({ })
block. That way you get to use all of the benefits of polymer and don't run into a scoping issue like in this problem.
Problems continue when trying to wrap the dialog in to another element. You can no longer access the dialog.open()
method because of the scoping of the element. dialog.open()
is only accessible inside of your my-dialog
element. To solve this you need to implement your own .open()
method. Code would look something like this:
<template>
<paper-dialog id="dialog">
//Your dialog content
</paper-dialog>
</template>
<script>
Polymer({
is: 'my-dialog',
open: function(){
this.$.dialog.open();
}
});
</script>
How it would look like in your index or other element in which you use it.
<my-dialog-button dialog-id="testdialog"></my-dialog-button>
<my-dialog id="testdialog"></my-dialog>
That way you can open the dialog inside the my-dialog
element.
Working example:
<!doctype html>
<head>
<meta charset="utf-8">
<!---- >
<base href="https://polygit.org/components/">
Toggle below/above as backup when server is down
<!---->
<base href="https://polygit2.appspot.com/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-fab/paper-fab.html" rel="import">
<link href="paper-dialog/paper-dialog.html" rel="import">
</head>
<body>
<dom-module id="my-dialog-button">
<style>
paper-fab.addbutton {
position: absolute;
right: -27px;
top: 34px;
}
</style>
<template>
<paper-fab class="addbutton" icon="add" on-tap="clickHandler"></paper-fab>
</template>
<script>
Polymer({
is: 'my-dialog-button',
properties: {
dialogId: {
type: String
}
},
clickHandler: function(e) {
var button = e.target;
while (!button.hasAttribute('dialogId') && button !== document.body) {
button = button.parentElement;
}
if (!button.hasAttribute('dialogId')) {
console.log("you have no element with 'dialogId' defined");
return;
}
var id = button.getAttribute('dialogId');
console.log("dialog " + id + " requested");
var dialog = document.getElementById(id);
if (dialog) {
dialog.open();
} else {
console.log("dialog " + id + " does not exist")
}
}
});
</script>
</dom-module>
<!--- ---------------------------------------------my dialog------------------------------------------------>
<dom-module id="my-dialog">
<template>
<paper-dialog id="dialog">
<h2>"hello world"</h2>
<p>"I am bob"</p>
</paper-dialog>
</template>
<script>
Polymer({
is: 'my-dialog',
open: function() {
this.$.dialog.open();
}
});
</script>
</dom-module>
<!-----------------------------page--------------------------------------->
<my-dialog-button dialogId="add-button"></my-dialog-button>
<my-dialog id="add-button"></my-dialog>
</body>
Side note:
When writing polymer elements you shouldn't need to declare any javascript code outside the Polymer({ });
. If you declare code outside of that block there is possibility of the scoping inside the project to mess up.