Polymer: Instance polymer element from another element - javascript

I'm wondering how could I instance a Polymer element when I click on another element. Is there a way to instance window-base from dock-icon? (code down). I though I could use the constructor every element has but I can't figure out how this works. How could I pass a variable to that constructor.
Code of the two elements involved:
<polymer-element name="dock-icon" attributes="name" on-click="{{click}}">
<template>
<link rel="stylesheet" href="dock-icon.css">
</template>
<script>
Polymer('dock-icon', {
name: "",
click: function (event, detail, sender) {
alert(this.name);
//instance <window-base> and pass name parameter
}
});
</script>
Polymer element that has to be instanced
<polymer-element name="window-base" attributes="name height width left top">
<template>
<link rel="stylesheet" href="window-base.css">
<div id="box">
<header id="header"><h2>{{name}}</h2></header>
</div>
</template>
<script>
Polymer('window-base', {
name: "name",
//more stuff here
});
</script>
Thanks

This should be straightforward as:
var el = document.createElement('window-base');
el.name = 'some name';

Related

Change one of many toggle button label with same function - Polymer

I have a bunch of paper-toggle-buttons that I am wanting to have the label display its current state.
I can get this to work simply enough on one button, but I am wanting to have them point to one function so that my code is cleaner.
I currently have this code, however both will toggle at the same time???
It's definitely the JS that is wrong.
Polymer({
is: 'example-element',
properties: {
labelText: {
type: String,
value: 'false'
}
},
checkToggle: function(e) {
var toggleButton = e.currentTarget.getAttribute('input');
this.$$('#' + toggleButton).checked ? this.labelText = "True" : this.labelText = "False";
},
});
<base href="https://polygit.org/polymer+polymer+v1.9.0/components/" />
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="paper-toggle-button/paper-toggle-button.html" />
<example-element></example-element>
<dom-module id="example-element">
<template>
<paper-toggle-button input="paper-toggle1" id="paper-toggle1" on-click="checkToggle">{{labelText}}</paper-toggle-button>
<paper-toggle-button input="paper-toggle2" id="paper-toggle2" on-click="checkToggle">{{labelText}}</paper-toggle-button>
</template>
</dom-module>
No point using a custom property for this, you may as well change the dom directly. This is just one way of doing it.
Polymer({
is: 'example-element',
properties: {
labelText: {
type: String,
value: 'false'
}
},
checkToggle: function(e) {
e.currentTarget.querySelector(".label").innerHTML = e.currentTarget.checked == true;
},
});
<base href="https://polygit.org/polymer+polymer+v1.9.0/components/" />
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="paper-toggle-button/paper-toggle-button.html" />
<example-element></example-element>
<dom-module id="example-element">
<template>
<paper-toggle-button input="paper-toggle1" id="paper-toggle1" on-click="checkToggle"><span class="label">false</span></paper-toggle-button>
<paper-toggle-button input="paper-toggle2" id="paper-toggle2" on-click="checkToggle"><span class="label">false</span></paper-toggle-button>
</template>
</dom-module>
Try changing only the innerText of the toggle which was clicked:
checkToggle : function(e) {
var toggleButton = this.$$('#' + e.currentTarget.getAttribute('input'));
toggleButton.checked ? toggleButton.innerText = "True" : toggleButton.innerText = "False";
}
Use the strength of properties.
<paper-toggle-button checked="{{paperToggle1}}">[[paperToggle1]]</paper-toggle-button>
<paper-toggle-button checked="{{paperToggle2}}">[[paperToggle2]]</paper-toggle-button>
You could do more advanced stuff as well, like saving each toggle button in an Object (paperToggle.first) nor adding a method that takes in the id and use that as a key in said Object.

Polymer 2.0: pass this to another element. Making a comments section

So basically what I'm struggling with is how to pass the reference of the parent element to its child element i.e the custom remove element?
can anyone please help me out!
*******************this is the el-insert element********************
// this element recieves data from another element(username and comment)
<link rel="import" href="./remove.html">
<dom-module id="el-insert">
<template >
<div id="userComment"><span>{{username}}</span>: {{saveComment}}</div>
<input id="edit" type="text" value={{saveComment::input}}>
<hr>
<reply-comment></reply-comment>
<button on-click="edit">Edit</button>
<remove-comment ></remove-comment>
</template>
<script>
class elInsert extends Polymer.Element {
static get is() { return 'el-insert'; }
static get properties(){
return {
saveComment:{
type:String,
notify:true
},
username:{
type:String,
notify:true
}
}//return ends
}
edit (){
$(this.$.userComment).toggleClass('hide');
var display = $(this.$.edit).css('display');
if(display == 'none'){
$(this.$.edit).css('display','block');
}else{
$(this.$.edit).css('display','none');
}
}
}
window.customElements.define(elInsert.is, elInsert);
</script>
</dom-module>
***************the remove button element******************
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="remove-comment">
<template>
<button on-click="remove">el-Remove</button>
</template>
<script>
class removeComment extends Polymer.Element {
static get is() { return 'remove-comment'; }
static get properties(){
return{
}//return ends
}
remove(){
var element = this.parentNode.host;
$(element).remove();
}
}
window.customElements.define(removeComment.is,removeComment);
</script>
</dom-module>
This code works perfectly for me.
But how will I do the same thing using fire or dispatch as mentioned in the answer by Nicolas.
How to pass event details from parent element to child element?
Also, I want to make this element reusable so that I can simply drop it into another place like in a reply to delete that also.
(Also, I'm new very new to polymer so if there is anything else that I can improve upon in this code then please let me know)
I hope now you guys can help me out.
You do not want to do that - in general you should just pass properties to the child element and catch events from the child in the parent elements.
properties go down and events go up -
In you case you do not have to pass anything to the child element. The child element should just fire an event and the parent should respond to it when it catches it.
Something like that:
<dom-module id="child-element">
<template>
<div on-tap="_deleteComment"></div>
</template>
<script>
class ChildElement extends Polymer.Element {
...
_deleteComment() : {
// fire event to be caught by parent
const deleteEvent = new CustomEvent('deleteComment', {detail: {
whatever: {
you: 'want',
},
}});
this.dispatchEvent(deleteEvent);
}
}
...
</script>
</dom-module>
<dom-module id="parent-element">
<template>
<child-element on-delete-comment="_deleteComment"></child-element>
</template>
<script>
class ParentElement extends Polymer.Element {
...
_deleteComment(evt) : {
// handle evt
}
}
...
</script>
</dom-module>
#daKmoR is right - more context and some code would help -

Polymer two-way binding between custom elements [example included]

I'm trying to make custom element within a custom element and have the inner custom element able to change its value from within and the outer able sync its binding on that change. What can I do to get this working?
I've thoroughly scoured the documentation, but it's very lackluster in this department. I believe Node.bind() may be something of interest, but not sure how it would apply in this case.
Here's a simplified test case and plunker demo:
<polymer-element name='test-app'>
<template>
First:
<test-input id='one' value='{{value}}'></test-input>
<br/>
<br/>
Second:
<test-input id='two' value='{{value}}'></test-input>
<br/>
<br/>
Value:
{{value}}
</template>
<script>
Polymer({
value: 5
})
</script>
</polymer-element>
<polymer-element name='test-input'>
<template>
<style>
#val {
font-size: 50px;
}
</style>
<div id='val'>{{value}}</div>
<button on-tap='{{increment}}'>+</button>
<button on-tap='{{decrement}}'>-</button>
</template>
<script>
Polymer({
publish: {
value: 4
},
increment: function() {
this.value = this.value + 1;
},
decrement: function() {
this.value = this.value - 1;
}
})
</script>
</polymer-element>
<test-app></test-app>
http://plnkr.co/edit/KjQ9DusaFg2jp1BTFUde?p=preview
If this was working, the value property of the test-app parent element should be in sync with both of the test-inputs value property.
Notice this warning in the console:
Attributes on test-input were data bound prior to Polymer upgrading the element. This may result in incorrect binding types.
test-app uses test-input before Polymer knows about test-input. All of an element's dependencies must be declared before that element is declared. Move test-input above test-app and it works as expected.
http://plnkr.co/edit/ZaIj60S3lAHT18k5T3sn?p=preview

How do I bind a function to elements inside of a Shadow DOM?

I'm working with Web Components and try to bind a click event to an element inside of the Shadow DOM.
1. component.html included as <link rel="import" ...> inside of index.html
<template id="my-element">
<section>
<header>
<content select="h1"></content>
<button></button>
</header>
<content select="div"></content>
</section>
</template>
2. later element usage:
<my-element>
<h1>Headline</h1>
<div>...</div>
</my-element>
3. Access element and bind a function to it
Now I want to add an addEventListener() to the <button> inside of my <my-element> (which is unfortunately hidden through the #shadow-root). Like:
var elemBtn = document.querySelector('my-element button');
elemBtn.addEventListener('click', function(event) {
// do stuff
});
But that won't work. How do I achieve that?
You should be able to do this without involving the window object. Here's a full example:
<!-- Define element template -->
<template>
<h1>Hello World</h1>
<button id="btn">Click me</button>
</template>
<!-- Create custom element definition -->
<script>
var tmpl = document.querySelector('template');
var WidgetProto = Object.create(HTMLElement.prototype);
WidgetProto.createdCallback = function() {
var root = this.createShadowRoot();
root.appendChild(document.importNode(tmpl.content, true));
// Grab a reference to the button in the shadow root
var btn = root.querySelector('#btn');
// Handle the button's click event
btn.addEventListener('click', this.fireBtn.bind(this));
};
// Dispatch a custom event when the button is clicked
WidgetProto.fireBtn = function() {
this.dispatchEvent(new Event('btn-clicked'));
};
var Widget = document.registerElement('my-widget', {
prototype: WidgetProto
});
</script>
<!-- Use the element -->
<my-widget></my-widget>
<!-- Listen for its click event -->
<script>
var widget = document.querySelector('my-widget');
widget.addEventListener('btn-clicked', function() {
alert('the button was clicked');
});
</script>
Example on jsbin
I found out that creating a custom createEvent('MouseEvent'); inside of <template> will do the trick!
TL;DR http://jsfiddle.net/morkro/z0vbh11v/
1. First, you need to add the onclick=""-attribute to our <template> and create a custom event:
<template id="my-element">
<section>
<header>
<content select="h1"></content>
<button onclick="callEventOnBtn()"></button>
</header>
<content select="div"></content>
</section>
<script>
var btnEvent = document.createEvent('MouseEvent');
btnEvent.initEvent('oncomponentbtn', true, true);
var callEventOnBtn = function() {
window.dispatchEvent(btnEvent);
};
</script>
</template>
I create the custom event inside of the <template> and automatically dispatch it to the global window object when the Custom Element gets used later.
2. Now we can listen to that event, when clicking the <button> on our custom element
window.addEventListener('oncomponentbtn', function(event) {
// do stuff
});

Polymer binding tap to an object method

I'm trying to bind a method to an on-tap attribute of a paper-button. After much testing, I've found that I can only bind a (for lack of a better word) top-level function, and not a method of an object in the template.
For example, I have a template, to which I have bound a number of objects, one of which is a user object. Object user has a bunch of methods and variables, like 'isNew' or 'reputation'. The user object also has a method 'addReputation'
I can use the object variables like this :
<template if = '{{user.new}}'><h1>{{user.name}}</h1></template>
And I can bind button taps like this:
<paper-button on-tap='{{addReputation}}'>Add Rep</paper-button>
But not like this:
<paper-button on-tap='{{user.addReputation}}'>Add Rep</paper-button>
Does anyone know why this may be?
if you set the method to a handler on your element's prototype it works. That way you can still keep things dynamic:
<script src="http://www.polymer-project.org/webcomponents.min.js"></script>
<script src="http://www.polymer-project.org/polymer.js"></script>
<polymer-element name="my-element" on-tap="{{tapHandler}}">
<template>
<style>
:host {
display: block;
}
</style>
click me
<content></content>
</template>
<script>
Polymer({
created: function() {
this.user = {
method: function() {
alert('hi');
}
};
this.tapHandler = this.user.method;
}
});
</script>
</polymer-element>
<my-element></my-element>
i'm sharing my plunk to resolve above problem. plunk link
In the template
<button on-tap="{{fncall}}" data-fnname="b">b call</button>
In the script
x.fncall = function(e) {
var target = e.target;
var fnName = target.getAttribute("data-fnname");
return x.datamodel[fnName]();
}
Polymer(x);

Categories