How to use dom-bind within test-fixture? - polymer

How can I use <template is="dom-bind"> within <test-fixture> with web-components-tester?
I have tried to use it Polymer 0.8 x-template way:
<test-fixture id="dom-bind-fixture">
<template is="dom-bind">
<h1>{{greeting}}</h2>
</template>
</test-fixture>
<script>
// ...
var bound = fixture('dom-bind-fixture', {greeting: 'ohai thurr'});
</script>
which naturally fails, as dom-bind does not have stamp method.
Then, I tried just stamping it out of native <template> element:
<test-fixture id="dom-bind-fixture">
<template>
<h1>outside dom-bind</h1>
<template is="dom-bind">
<h2>inside dom-bind</h2>
</template>
</template>
</test-fixture>
But in non-Chrome browsers this one stamps only outside dom-bind.
Is there a way to make it work, or is it just a blocking bug in web-components-tester/test-fixture/dom-bind?

Use dom-template, ie:
<test-fixture id="dom-bind-fixture">
<template is="dom-template">
<h1>{{greeting}}</h2>
</template>
</test-fixture>
<script>
// ...
var bound = fixture('dom-bind-fixture', {greeting: 'ohai thurr'});
</script>

Related

Polymer dom-if: how do I implement a negative condition?

I have a Polymer element that uses <template is="dom-if"... to provide different HTML content depending on a condition.
Polymer dom-if has no else condition, so needs a negative if condition to simulate it.
Something like this:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<dom-module id="test-thing">
<template>
<template is="dom-if" if="{{title}}" restamp>
<b>[[title]]</b>
</template>
<template is="dom-if" if="{{!title}}" restamp>
<i>no title</i>
</template>
</template>
<script>
Polymer({
is: 'test-thing',
properties: {
title: String
}
});
</script>
</dom-module>
<div>
With negative condition:
<test-thing></test-thing>
</div>
<div>
With positive condition:
<test-thing title="Has Title"></test-thing>
</div>
Only that doesn't work - the negative condition never passes.
How should this be implemented?
You must use a default empty value for your title property:
title:{type: String,value:''}
Like so:
<link href="https://polygit.org/components/polymer/polymer.html" rel="import">
<dom-module id="test-thing">
<template>
<template is="dom-if" if="{{title}}" restamp>
<b>[[title]]</b>
</template>
<template is="dom-if" if="{{!title}}" restamp>
<i>no title</i>
</template>
</template>
<script>
Polymer({
is: 'test-thing',
properties: {
title: {type: String,value:''}
}
});
</script>
</dom-module>
<div>
With negative condition:
<test-thing></test-thing>
</div>
<div>
With positive condition:
<test-thing title="Has Title"></test-thing>
</div>

Polymer element is unregistered

I've created an element to display the results of an API call, but it not rendering. I've used the 'unregistered element' bookmarklet from the Polymer team which is showing this as unregistered. I'm using this within the Polymer starter kit.
I'm sure its a simple oversight on my behalf that I'm just not seeing.
The element is is listed in the elements.html file and is used in the main index.html file like so.
<section data-route="driver-standings">
<driver-standing></driver-standing>
</section>
The element
<dom-module id="driver-standing">
<template>
<style>
:host {
display: block;
}
</style>
<iron-ajax
auto
url="http://ergast.com/api/f1/current/driverStandings.json"
handle-as="json"
last-response="{{data}}"></iron-ajax>
<template is="dom-repeat" items="{{driverList}}">
<span>[[item.Driver.givenName]]</span> <span>[[item.Driver.familyName]]</span>
<template>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'driver-standing',
properties: {
data: {
},
driverList: {
computed: 'processDrivers(data)'
}
},
processDrivers: function (data){
console.log("processDrivers")
return data.MRData.StandingsTable.StandingsLists[0].DriverStandings;
}
});
})();
</script>
</dom-module>
Any help much appreeciated
I missed the closing / on the template tag.
<template is="dom-repeat" items="{{driverList}}">
<span>[[item.Driver.givenName]]</span> <span>[[item.Driver.familyName]]</span>
<template>
became...
<template is="dom-repeat" items="{{driverList}}">
<span>[[item.Driver.givenName]]</span> <span>[[item.Driver.familyName]]</span>
</template>
Easily missed :)
Your dom-repeat - template should look some kind of this:
You should have your items you want to display in the item tag and as Polymer goes throw your Array it safes each Object under the name defined under the as - tag, so you can access the Object inside of your template binding with the name in curly brackets, like {{driver}}
<template is="dom-repeat"
items="{{driverList}}"
as="driver">
<p>{{driver}}</p>
</template>

Polymer iron-list dynamically adding items?

I'm trying to migrate some code from Polymer 0.5 to 1.x, this means moving from core-list to iron-list. However, I can not figure out an iron equivalent to how I was adding items to the core-list.
<core-list height="85">
<template>
<div class="{{ {selected: selected} | tokenList }}" style="padding:5px;"><paper-fab mini icon="arrow-forward" title="arrow-forward"></paper-fab> <!--{{index}}-->{{model.name}}</div>
</template>
</core-list>
which is called updated via...
document.querySelector('core-list').data = $.parseJSON('[{"name":"One"},{"name":"Two"}]');
Anyone have any suggestions?
Update : Jul-23-2015 12:20PM PST
#Zikes
Following the suggestion posted, I have the following.
<dom-module id="my-element">
<template>
<iron-list items="[[myItems]]" as="item">
<template>
<div>[[item.name]]</div>
</template>
</iron-list>
</template>
<script>
Polymer({
is:'my-element',
properties: {
myItems: Array
},
addItem: function(item) {
this.push('myItems', {name: item});
}
});
</script>
</dom-module>
If this is setup right, how would I go about calling the addItem method from elsewhere?
Update : Jul-23-2015 1:58PM PST
#Zikes
Following is my current code. While I can manipulate the array, values added to it in the ready or addItem method are not being displayed.
<dom-module id="fnord-element">
<template>
<iron-list items="[[myItems]]" as="item">
<template>
<div class="item">[[item.name]]</div>
</template>
</iron-list>
</template>
<script>
Polymer({
is:'fnord-element',
properties: {
myItems: {
type: Array,
notify: true
}
},
addItem: function(item) {
//this.push("myItems", {"name":item});
this.myItems=[{name:item}];
alert(this.myItems[0].name);
//alert(item);
},
ready: function() {
//alert('fnord');
this.myItems=[{name:"One"},{name:"Two"}];
}
});
</script>
</dom-module>
<fnord-element id="fnord"></fnord-element>
<paper-button raised onclick="document.querySelector('#fnord').addItem('John Doe');">Test</paper-button>
iron-list uses the items property to generate its items, similar to dom-repeat. What you can do is simply bind it to an Array in your component, like so:
<dom-module id="my-element>
<template>
<iron-list items="[[myItems]]">
<template>
<div>[[item]]</div>
</template>
</iron-list>
</template>
<script>
Polymer({
is:'my-element',
properties: {
myItems: Array
}
});
</script>
</dom-module>
Then, just follow the rules for modifying an Array property and you're all set!

Alternative to "in" expression for iterating over objects polymer (0.5.4)

Using the repeat and in expression it is trivial to iterate over arrays, but swapping
this.data = ["foo","bar"];
to
this.data = {foo:"football",bar:"barfly"}
fails to iterate over the object. I have seen examples of using Object.key in order to get each value, but the index returned is 0,1 instead of "foo" "bar".
While this simple example doesn't use 2 way binding, I would like to keep support for it, in case I need it in the future.
http://jsbin.com/copogeyome/1/
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Polymer</title>
<script src="http://www.polymer-project.org/components/webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
</head>
<body>
<polymer-element name="an-consumer" attributes="data" noscript>
<template>testing {{data.foo}}<br>
<template id="foo">f {{}}<br></template>
<template id="bar">b {{}}<br></template>
<template id="0">0 {{}}<br></template>
<template id="1">1 {{}}<br></template>
<template id="2">2 {{}}<br></template>
{
<template repeat="{{obj,index in data}}" bind="{{data}}">
( {{index}} - {{obj}} ) = <template ref="{{index}}" bind="{{obj}}"></template>
</template>
}
</template>
</polymer-element>
<polymer-element name="an-supplier" attributes="data">
<template></template>
<script>
Polymer({
ready: function(){
this.data = ["foo","bar"];
//this.data = {foo:"football",bar:"barfly"}
}
});
</script>
</polymer-element>
<polymer-element name = "an-root" noscript>
<template>
<an-supplier data="{{stuff}}"></an-supplier>
<an-consumer data="{{stuff}}"></an-consumer>
</template>
</polymer-element>
<an-root>
</an-root>
</body>
</html>
While there is [yet] no built-in ability to iterate over object, you might easily achieve this functionality with filter:
<template repeat="{{key in data | getKeys}}">
<span>Key: {{key}}</span>
<span>Value: {{data[key]}}</span>
</template>
<script>
Polymer({
ready: function(){
// this.data = ["foo","bar"];
this.data = {foo:"football",bar:"barfly"}
}
// filter function to use in looping objects
getKeys : function(o) {
return Object.keys(o);
}
});
</script>
Whether you have additional questions, please, don’t hesitate to ask.
Live: http://jsbin.com/munehitogu/1/edit

how to inject <template> into polymer component by providing it as element content

i want to inject a template into an polymer component like this :
<polymer-element name="foo-bar">
<template>
<content></content>
<!-- content is expected to contain a template with id="layout"-->
<template bind ref="layout">
default content template
</template>
</template>
<script src="index.js"></script>
</polymer-element>
usage of the component :
<foo-bar>
<template id="layout">another content template</template>
</foo-bar>
unfortunately the template provided as content of the element is not taken over for some reason.
when simluate the wished behaviour using
<polymer-element name="foo-bar">
<template>
<template id="layout">
custom content template
</template>
<template bind ref="layout">
default content template
</template>
</template>
<script src="index.js"></script>
</polymer-element>
the referenced template(id="layout") is used as expected.
Any help is appreciated :-)
<template ref="layout"> says use the template#layout for my content. So I would expect the template in your shadow dom to use the content of the light dom template. This is what you see in http://jsbin.com/takipi/1/edit.
However, if you want to use render the light dom <template> the user provides, you must activate it using template.createInstance(). By default, templates are inert. For this use case, you also don't need <content>. That's for rendering and in this case, it doesn't really make sense.
The example below also show how to set things up. It also shows how you can use {{}} bindings in the light dom <template> and fill them when the instance is created.
<div id="container"></div>
<template if="{{showDefault}}">
default content template
</template>
attached: function() {
var template = this.querySelector('template');
if (template) {
this.$.container.appendChild(
template.createInstance({foo: 5}));
this.showDefault = false;
}
}
Full code:
<script src="http://www.polymer-project.org/platform.js"></script>
<script src="http://www.polymer-project.org/polymer.js"></script>
<polymer-element name="foo-bar">
<template>
<div id="container"></div>
<template if="{{showDefault}}">
default content template
</template>
</template>
<script>
Polymer({
showDefault: true,
attached: function() {
var template = this.querySelector('template');
if (template) {
// Allow Polymer expressions in the template's {{}}.
if (!template.bindingDelegate) {
template.bindingDelegate = this.element.syntax;
}
this.$.container.appendChild(
template.createInstance({foo: 5}));
this.showDefault = false;
}
}
});
</script>
</polymer-element>
<foo-bar>
<template>
<b>another</b> content template. Also supports data: {{foo}}
</template>
</foo-bar>