Nested Polymer Components Content Issue - javascript

foo.html:
<link rel="import" href="bar.html">
<dom-module id="p-foo">
<template>
<p-bar>
<content select=".myContent"></content>
</p-bar>
</template>
<script>
Polymer( {
is: 'p-foo',
} )
</script>
</dom-module>
bar.html:
<dom-module id="p-bar">
<template>
bar open
<content select=".myContent"></content>
bar closed
</template>
<script>
Polymer( {
is: 'p-bar',
} )
</script>
</dom-module>
demo.html:
<!DOCTYPE html>
<html>
<head>
...
<link rel="import" href="foo.html">
</head>
<body>
<p-foo><div class="myContent"><strong>hello</strong></div></p-foo>
</body>
</html>
The expected output:
bar open
hello
bar closed
What I sometimes get:
bar open
bar closed
hello
The error I am getting is not 100% reproducible. It only happens a percentage of the time I refresh the page. It also appears that the more complicated the content is the higher chance of the error occurring.
It seems that polymer tries to select .myContent before the bar component is has completely rendered.

You need to register your new custom elements with a call to Polymer().
Also, as already stated in comments, your custom elements need to contain an hypen. For example: <p-foo>and <p-bar>.
foo.html:
<link rel="import" href="bar.html">
<dom-module id="p-foo">
<template>
<p-bar>
<content select=".myContent"></content>
</p-bar>
</template>
<script>
Polymer( {
is: 'p-foo',
} )
</script>
</dom-module>
bar.html:
<dom-module id="p-bar">
<template>
bar open
<content select=".myContent"></content>
bar closed
</template>
<script>
Polymer( {
is: 'p-bar',
} )
</script>
</dom-module>
demo.html:
<head>
...
<link rel="import" href="foo.html">
</head>
<body>
<p-foo><div class="myContent"><strong>hello</strong></div></p-foo>
</body>
</html>

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>

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>

How can I change polymer element template by passing param attribute

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

Polymer webcomponents data binding an js object/array

On https://www.polymer-project.org/1.0/ the show the usage with firebase as datasource. However I'd like to use a simple js variable (array/object) as datasource e.g. an array with friends. However I'm not getting the array bound to the polymer.
How can I bind an js array as data bining to an polymer?
Example HTML Page index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="friends-list.html">
</head>
<body>
<h1>Hello Data Object Arry Binding</h1>
<script>
var friends = [
{"name":"manual"},
{"name":"john"},
{"name":"doe","starred":true}
];
</script>
<friend-list data="friends"></friend-list>
</body>
</html
with expecting friend-list.html polymar may be something like this:
<dom-module id="friend-list">
<link rel="import" type="css" href="friend-list.css">
<template>
<template is="dom-repeat" items="{{data}}">
<contact-card starred="{{item.starred}}">
<img src="{{item.img}}">
<span>{{item.name}}</span>
</contact-card>
</template>
</template>
<script>
Polymer({
is: 'friend-list',
properties: {
data: Object
}
});
</script>
</dom-module>
You have to use dom-bind template if you want to use data binding outside of an element declaration.
<template is="dom-bind" id="app">
<h1>Hello Data Object Arry Binding</h1>
<friend-list data="{{friends}}"></friend-list>
</template>
<script type="text/javascript">
var app = document.getElementById('app');
app.friends = [
{"name":"manual"},
{"name":"john"},
{"name":"doe","starred":true}
];
</script>

How to discuss between custom Polymer elements without events

I would like to discuss between custom elements without events in a parent custom element.
How could I do this, if it's possible ?
This is my-custom-parent-element.htlm :
<link rel="import" href="../my-custom-elment-1.html">
<link rel="import" href="../my-custom-elment-2.html">
<polymer-element name="my-custom-parent-element" noscript>
<template>
<my-custom-elment-1></my-custom-elment-1>
<my-custom-elment-2></my-custom-elment-2>
</template>
</polymer-element>
this is my-custom-element-1 :
<link rel="import" href="../polymer-gestures/polymer-gestures.html">
<polymer-element name="my-custom-element-1">
<template>
<div><canvas width="300px" height="200px"></canvas></div>
</template>
<script>
Polymer({
ready: function() {
<!-- Here, I need notify my-custom-element-2 that canvas received an event without re-send an event-->
}
});
</script>
</polymer-element>
this is my-custom-element-2 :
<polymer-element name="my-custom-element-2">
<template>
<div></div>
</template>
<script>
Polymer({
ready: function() {
<!-- Here, I need to change value by my-custom-element-1 notifications -->
}
});
</script>
</polymer-element>
Not sure either how you want to do this.
But you can also give reference to elem1 from the parent :
<polymer-element name="my-custom-parent-element" noscript>
<template>
<my-custom-elment-1 id="elem1"></my-custom-elment-1>
<my-custom-elment-2 id="elem2"></my-custom-elment-2>
</template>
<script>
Polymer({
domReady: function() {
this.$.elem1.target = this.$.elem2
}
});
</script>
</polymer-element>
And in elem1 :
<polymer-element name="my-custom-element-1" attributes="target">
<template>
<div><canvas width="300px" height="200px"></canvas></div>
</template>
<script>
Polymer({
ready: function() {
<!-- Here, I need notify my-custom-element-2 that canvas received an event without re-send an event-->
target.xxx();
}
});
</script>
</polymer-element>
But usually, the event way is better

Categories