How can I change polymer element template by passing param attribute - javascript

I'm creating a slider web component from scratch to learn.
I want the button to hide when the attribute controlVisible is false and show when it's true, but my selector $('#botaoVoltar') doesn't get anything.
What am I missing?
index.html:
<body>
<slider-js controlVisible='false' ></slider-js>
</body>
polymer.html:
<polymer-element name="slider-js">
<template>
<center>
<div id="container">
<div id="Buttons">
<button name="voltar" id="botaoVoltar"><<</button>
</div>
</div>
</center>
</template>
</polymer-element>
<script>
Polymer('slider-js', {
controlVisible: false,
ready: function () {
if (this.controlVisible === false) {
$('#botaoVoltar').hide();
} else {
$('#botaoVoltar').show();
}
}
});
</script>
The attribute is working fine. If I console.log it, I can see if it is true or false, but the template still renders with the button.

jQuery can't get at Polymer's local DOM, so you'd have to use Polymer's own DOM API. Actually, Polymer's automatic node finding provides quick access to nodes that have IDs with this.$. For instance, you could access the botaoVoltar button in your example with this.$.botaoVoltar.
It looks like you're using old Polymer (pre 1.0). You should switch to the latest version of Polymer (1.5.0). Here's your code upgraded to the newest Polymer version:
<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>
<span>With control-visible:</span>
<x-slider control-visible></x-slider>
<span>Without control-visible:</span>
<x-slider></x-slider>
<!-- Normally, you would define this element in its own file. -->
<dom-module id="x-slider">
<template>
<div id="container">
<div id="Buttons">
<button id="botaoVoltar"><<</button>
<button>>></button>
</div>
</div>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-slider',
properties : {
controlVisible: {
type: Boolean,
value: false
}
},
ready: function() {
this.$.botaoVoltar.hidden = !this.controlVisible;
}
});
});
</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

Get reference to dynamically created element

In Polymer you can use this.$.idOfElement to get an element with an id of idOfElement.
How can I get a dynamically created element by its id if I only have the value of id in a variable?
Note: The element I want to reach out to is created dynamically like this:
<template is="dom-repeat" items="[[days]]" as="o">
<my-custom-element id$="[[getId(o)]]"></my-custom-element>
</template>
I have plenty of these <my-custom-element> in my app and need to get hold of them one by one.
Edit:
None of these work, they all return undefined or null:
this.$[id]
this.$$(id)
this.root.querySelector('my-custom-element#' + id)
Polymer.dom(e.currentTarget).querySelector('my-custom-element#' + id)
You cannot use the automatic node finder (this.$.x) for dynamic nodes. You have to use this.$$(selector), which acts like document.querySelector() constrained to children of the current element.
This why you must use this.$$('#' + nodeId) as suggested by Alan.
Polymer({
is: 'my-elem',
makeRed: function() {
this.$$('#li2').style.color = 'red';
}
});
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import"/>
</head>
<body>
<my-elem></my-elem>
<dom-module id="my-elem">
<template>
<ul>
<template is="dom-repeat" items='[ 1, 2, 3 ]'>
<li id="li[[item]]">{{item}}</li>
</template>
</ul>
<input type="button" value="make 2 red" on-tap="makeRed" />
</template>
</dom-module>
</body>
</html>

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

<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

How to dynamically add component into a div in another component?

I got an error when I want try to add a component into a div DOM in another component.
Uncaught Error: Assertion Failed: You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.
here is my JSBin
App = Ember.Application.create();
App.MyListComponent= Ember.Component.extend({
layoutName:'my-list',
actions:{
addItem:function(){
console.log("add item action");
App.MyListItemComponent.create().appendTo("#holder");
},
},
});
App.MyListItemComponent= Ember.Component.extend({
layoutName:'my-list-item',
});
html, body {
margin: 20px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://builds.emberjs.com/release/ember-template-compiler.js"></script>
<script src="http://builds.emberjs.com/release/ember.debug.js"></script>
</head>
<body>
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{my-list}}
</script>
<script type="text/x-handlebars" id="my-list">
<button {{action "addItem"}}>add item</button>
This is a holder:
<div id="holder">
i am inside holder
</div>
This is static item:
{{my-list-item}}
</script>
<script type="text/x-handlebars" id="my-list-item">
i am a list item
</script>
</body>
</html>
can you have a look and tell me how to do?
thank you very much
I dont think, your approach is right.
A component should be working independently from the context in which it is added. You can pass anything as argument to the component within the template. I would recommend displaying the components depending on some type of model that is added with each addItem click (in my example, a simple text).
Why don't you try it this way:
JS
App = Ember.Application.create();
App.MyListComponent= Ember.Component.extend({
components: Ember.A([]),
layoutName:'my-list',
actions:{
addItem:function(){
var components = this.get('components');
console.log(components);
components.pushObject ('test'); // or whatever you want: could also be components.pushObject(App.MyListItemComponent.create()); if you want to use it later somehow.
this.set('components', components);
console.log("add item action");
},
},
});
App.MyListItemComponent= Ember.Component.extend({
layoutName:'my-list-item',
});
html
<script type="text/x-handlebars" id="my-list">
<button {{action "addItem"}}>add item</button>
This is a holder:
<div id="holder">
i am inside holder {{components.length}}
{{#each components as |item|}}
{{my-list-item}}
{{/each}}
</div>
This is static item:
{{my-list-item}}

Categories