How to share variables with siblings? - html

I'm very new to Polymer, so please don't hold back any information!
I have a basic webpage with a standard format, and I'm trying to figure out how I can expose the #nav component variable currentSelection with the #main component, which depends on the selection for switching out the correct template:
head
body
div#nav
div#main
div#footer
I understand the encapsulation aspect of Polymer, but I lack an understanding of the glue, eventing system, and different instantiation patterns for the dynamic HTML, especially since Polymer 0.5 is deprecated.
Does <template is="dom-bind"> actually render as if it weren't a <template>? I'm thinking to wrap the whole site in one, but I'm not sure that's a good idea.

Why not make your #nav and #main custom components? That way you could bind to currentSelection like so:
<my-nav current-selection="{{currentSelection}}"></my-nav>
<my-main current-selection="[[currentSelection]]"></my-main>
The dom-bind template is necessary to make bindings work between elements in the main document (i.e index.html), so you could either use dom-bind:
<template is="dom-bind">
<my-nav current-selection="{{currentSelection}}"></my-nav>
<my-main current-selection="[[currentSelection]]"></my-main>
<my-footer></my-footer>
</template>
Or you could put all of your elements in another custom component such as my-app in which the bindings will work:
index.html
<body>
<my-app></my-app>
</body>
my-app.html
<template>
<my-nav current-selection="{{currentSelection}}"></my-nav>
<my-main current-selection="[[currentSelection]]"></my-main>
<my-footer></my-footer>
</template>

Related

Polymer access elements within vaadin-grid

Working jsbin illustrating the problem: http://jsbin.com/nomewa/3/edit?html,console,output
I am trying to set the innerHTML of notworking span inside of a template that makes up the vaadin-grid. It does not currently seems to be possible to bind to on-change of vaadin-checkbox when said vaadin-checkbox lies within vaadin-grid since I cannot even access the element within the grid.
It does not currently seems to be possible to bind to on-change of vaadin-checkbox when said vaadin-checkbox lies within vaadin-grid since I cannot even access the element within the grid.
You can use declarative event bindings inside the column tempates, so you don’t have to have a reference to the actual stamped element.
Something like this:
<vaadin-grid-column>
<template>
<vaadin-checkbox on-checked-changed="_myListener">Checkbox</vaadin-checkbo>
</template>
</vaadin-grid-colum>
This is a great way to try some codes (jsbin :) Here this code works but I do not know is it going to fit your need. (I cut and copied only changed parts :
At the property declaration, you may set a pre-value to notWorking property. Then you may change it with dynamically in a function.
<iron-ajax url="https://randomuser.me/api?results=10" last-response="{{response}}" auto></iron-ajax>
<span id="working">Working</span>
<vaadin-grid id="grid" items="{{response.results}}" style="height: auto;">
<vaadin-grid-column>
<template class="header">Name</template>
<template>[[item.name.first]] [[item.name.last]] <span>{{notWorking}}</span></template>
</vaadin-grid-column>
</vaadin-grid>
</template>
<script>
class MyTest extends Polymer.Element {
static get is() { return 'test-component'; }
ready() {
super.ready();
this.set('notWorking',"test")
debugger;
}
}
Here the working link

Call Method of Child Web Component

I'm really having difficulty trying to figure out how to call a function of a nested Polymer web component.
Here's the markup:
<rise-playlist>
<rise-playlist-item duration="5">
<rise-distribution distribution='[{"id":"VGZUDDWYAZHY"}]'></rise-distribution>
</rise-playlist-item>
</rise-playlist>
The rise-distribution component has a canPlay function that I would like to call from inside of rise-playlist.
The dom-module definition of rise-playlist looks like this:
<dom-module id="rise-playlist">
<template>
<content id="items" select="rise-playlist-item"></content>
</template>
</dom-module>
I can successfully access the rise-distribution element like this:
var distribution = Polymer.dom(this.$.items[0]).querySelector("rise-distribution");
However, when I try to call distribution.canPlay(), it says that distribution.canPlay is not a function.
I've defined the dom-module of rise-playlist-item like this:
<dom-module id="rise-playlist-item">
<content id="dist" select="rise-distribution"></content>
</dom-module>
Not sure if I need that <content> tag, although neither works.
Any ideas?
Thx.
I know that there have been a while but I am sure this problems still occurs as it is being viewed number of times.
Probably there is a problem with your component definition. Let me explain.
This is the way you put your child component inside DOM:
<your-child-component></your-child-component>
And and this should be the definition of your component:
Polymer({
is: 'your-child-component',
apiMethod: function() {
//some stuff
}
});
If you by mistake or due copy-paste error mistype the is: 'your-child-component' part, so it will not reflect the <your-child-component> you will get confused becouse your:
this.$$('your-child-component').apiMethod();
will tell you that there is no method you are willing to call.
Polymer correctly identified and selected from DOM <your-child-component> but if you have different is property (like for example is: your_child_component>) it will not attach its API to dom element you selected.
I hope that it will help if anyone ever will encounter this problem.

Polymer elements: to nest or not to nest?

We're developing a data visualization library using Polymer, and I must say I'm impressed with what Polymer lets you do. We do have a question, though...
First: here's an example snippet of code showing a data visualization:
<template is="auto-binding">
<our-loaddata url="data/data.csv" data="{{data}}"></our-loaddata>
<our-scatterplot data="{{data}}"></our-scatterplot>
<our-barchart data="{{data}}" dimension="weight"></our-barchart>
<our-histogram data="{{data}}" dimension="weight" binSize=10></our-histogram>
</template>
The our-loaddata loads the dataset from a file data/data.csv, performs some transformations (e.g. converting strings to numbers, calculating distributions, ...) and makes it available through {{data}} to the our-scatterplot, our-barchart and our-histogram. However, I'm not completely satisfied with the setup. Conceptually, the our-loaddata is different from the other three, and should precede them. As an alternative, we have also tried the following (renaming loaddata to app and nesting all visuals within the app):
<template is="auto-binding">
<our-app url="data/data.csv" data="{{data}}">
<our-scatterplot data="{{data}}"></our-scatterplot>
<our-barchart data="{{data}}" dimension="weight"></our-barchart>
<our-histogram data="{{data}}" dimension="weight" binSize=10></our-histogram>
</our-app>
</template>
Although this also works, we noticed that it doesn't matter if we close the </our-app> element before or after all the visual elements.
What would be the most canonical way to handle this in Polymer? What is the difference between the approaches that I showed here?
you could use the conditional template to check if data is present and then send the other elements to the dom if true or show a loader if false. (careful getting to used to this i don't think it is currently in 0.8. sad IMO i <3 it)
<template is="auto-binding">
<our-loaddata url="data/data.csv" data="{{data}}"></our-loaddata>
<template if="{{data}}">
<our-scatterplot data="{{data}}"></our-scatterplot>
<our-barchart data="{{data}}" dimension="weight"></our-barchart>
<our-histogram data="{{data}}" dimension="weight" binSize=10></our-histogram>
</template>
<template if="{{!data}}">
<pretty-loadingscreen></pretty-loadingscreen>
</template>
</template>
the would give you seperation of elements you were looking for.

dynamically pass in template to polymer-element

I have been trying create a polymer-element that generates a ul list based on an ajax request and then renders the "li" elements based on templates that can somehow be passsed in.
It's basically an attempt to make a polymer rebuild of the 'select2' library for autocompletion.
So, the base template I have so far looks like this:
<polymer-element name="auto-complete" attributes="url_base item_template">
<aj-ax id="xhr" url="{{url_base}}" params="{}" handle_as="json" on-ajax-response="{{handle_res}}" on-ajax-error="{{handle_err}}"></aj-ax>
<input id="eingabe" type="text" on-keyup="{{process_request}}" on-blur="{{hide_dropdown}}"/>
<div id="dropdown" hidden?="{{hide}}">
<ul>
<template repeat="{{i in items}}">
<li> i.text
<!--
the process_request handler makes the ajax request and sets
the "items" and un-hides the dropdown.
the above works, but I want to make it more generic so that
you can pass in a template that reads the item model such as
<template ref="{{item_template}}" bind></template>
where item_template is the ID of a template in some outside
scope
-->
</li>
</template>
</ul>
</polymer-element >
</div>
I've also tried to make a base auto-complete.html polymer-element and then extend it based on the auto-complete type...but to no avail.
Any thoughts, ideas?
I want to stick to declarative methods if possible and avoid having to build the DOM elements myself with document.createElement
Is that even possible?
thanks!
I've come up with a cool approach to do this actually!
http://jsbin.com/hesejipeha/2/edit
The main idea is that you conditionally render the your template once you've injected any child templates into the shadow DOM (and thus made it possible to call them by ref in scope!)

Is it possible to inject HTML into a polymer component via an attribute?

I'm using one of the core polymer components that basically has:
<polymer-element attributes="label">
<div>{{label}}</div>
as part of the source. I'd like to inject some HTML into this so that it ultimately renders as:
<div>Item <small>Description</small></div>
Is there any way to do this without copying the entire component (which is basically impossible considering the dependency chain)?
Polymer doesn't allow setting HTML inside {{}} expressions because it's a known XSS outlet. However, there are ways around it (1, 2).
I'm not sure there's a great way around this issue but I found something that works. You want to extend the element but also need to modify its shadow dom because of the .innerHTML limitation. Taking paper-button as an example, it has an internal {{label}}. You could extend the element, drill into its shadow dom, and set .innerHTML of the container where {{label}} is set. React to label changing (labelChanged) and call this.super():
<polymer-element name="x-el" extends="paper-button">
<template>
<shadow></shadow>
</template>
<script>
Polymer('x-el', {
labelChanged: function() {
// When label changes, find where it's set in paper-button
// and set the container's .innerHTML.
this.$.content.querySelector('span').innerHTML = this.label;
// call paper-button's labelChanged().
this.super();
}
});
</script>
</polymer-element>
Demo: http://jsbin.com/ripufoqu/1/edit
Problem is that it's brittle and requires you to know the internals of the element you're extending.