How to pass object literals as polymer attributes - javascript

In order to test some polymer custom elements of mine in isolation, I would like to be able to pass in js object literals for some attributes that would ordinarily come from parent elements. I'm having trouble figuring out how to do this. See this example code. If it were working as I would like it to, it would display a 1 and a 2 next to each other, but it doesn't work.
<script src="http://www.polymer-project.org/webcomponents.js"></script>
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<polymer-element name="my-element" attributes="stuff">
<template>
{{stuff.one}} {{stuff.two}}
</template>
<script>
Polymer('my-element', {
ready: function () {
console.log(this.stuff);
}
});
</script>
</polymer-element>
<my-element stuff='{"one": 1, "two": 2}'></my-element>

Polymer only converts the JSON text into an object, if you initialize the stuff property with an empty hash:
Polymer('my-element', {
stuff: {},
ready: function () {
console.log(this.stuff);
}
});
Without this, the stuff attribute is passed in as a string. The same goes for arrays.

Another way to do it:
myElem.html
<link rel="import"
href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<dom-module id="my-element">
<template>
<div> {{stuff.one}} {{stuff.two}} </div>
</template>
<script>
Polymer({
is: "my-element",
properties: {
stuff:{
type: Object,
value: {"one":"default_1","two":"default_2"}
}
}
});
</script>
</dom-module>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="myElem.html">
</head>
<body>
<my-element></my-element>
<my-element stuff={"one":"1","two":"2"}></my-element>
</body>
</html>
Result
default_1 default_2
1 2

index.html
...
<body unresolved fullbleed layout vertical>
<my-post info='{"name":"Alex","id":"123"}' posts='[{"id":"456","name":"post1"},{"id":"789","name":"post2"}]'></my-post>
</body>
...
my-post.html
<link rel="import" href="../../bower_components/polymer/polymer.html">
<polymer-element name="my-post" attributes="info posts" >
<template>
{{info.name}}
<template repeat="{{post in posts}}">
<br> {{post.id}} - {{post.name}}
</template>
</template>
<script>
(function () {
Polymer({
ready: function() {
this.info=JSON.parse(this.info)
this.posts=JSON.parse(this.posts)
},
});
})();
</script>
</polymer-element>

Related

Making polymer dom-repeat to work when a HTML block is added using .innerHTML

I am working on a polymer app where I need to fetch some HTML code block of code from external file and append to active file. I have specified the content to add myself.
Below is the code
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title></title>
</head>
<body>
<!-- Bootstrap Core CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link rel="import" href="bower_components/polymer/polymer.html">
<dom-module id="trail-app">
<template>
<style>
</style>
<button on-tap="loadContent">click</button>
<button on-tap="showContent">show</button>
<template is="dom-repeat" items='{{celsius}}'>
<div>[[item]]</div>
</template>
<div id="content"></div>
</template>
<script>
Polymer({
is: "trail-app",
properties:{
celsius:{}
},
ready:function(){
this.celsius = ["36","37","38","39","40","41"];
},
loadContent:function(data){
document.getElementById("content").innerHTML = '<template is="dom-repeat" items="{{Celsius}}">'+
'<div>[[item]]</div>'+
'</template>';
},
showContent:function(){
console.log(document.getElementById("content").innerHTML);
},
});
</script>
</dom-module>
<trail-app></trail-app>
</body>
</html>
when I loop through celsius using dom-repeat its working fine.
but if the same code is added using document.getElementById("content").innerHTML its giving
Polymer::Attributes: couldnt decode Array as JSON warning.
How to resolve this.
So I've addressed dynamic content like this using the templatizer behavior (https://www.polymer-project.org/1.0/docs/api/Polymer.Templatizer).
To use, create just a plain template with your dom-repeat inside that. Then in your loadContent method that's where you'll apply templatize and then stamp the template into the DOM.
<template id="repeatTempl">
<template is="dom-repeat" items="{{Celsius}}">
<div>[[item]]</div>
</template>
</template>
Include the Templatizer behavior:
behaviors: [Polymer.Templatizer]
Then your loadContent method would look something like this:
loadContent: function(data) {
var templ = this.$.repeatTempl;
this.templatize(templ);
var elem = this.stamp({Celsius: data});
Polymer.dom(this.$.content).appendChild(elem.root);
}

How can I access custom CSS property from JavaScript in Polymer?

I'm using Polymer and would like to be able get the value of a custom CSS property in JavaScript.
I thought I'd be able to do it using this.customStyle["--my-style"] but this was not the case (the result is undefined). You can see the element below:
<dom-module id="my-element">
<template>
</style>
<div>Some Content</div>
</template>
<script>
Polymer({
is: "my-element",
attached: function () {
console.log(this.customStyles["--my-style"])
}
})
</script>
</dom-module>
Is there anyway I can access this custom style from within the JavaScript - I'm able to set the value, just not retrieve it.
customStyles is an empty object which you populate while updating the properties. If you need to retrieve any value Polymer has provided another api getComputedStyleValue.
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<dom-module id='computed-style'>
<template>
<style>
:host {
--my-style: red;
}
.test {
color: var(--my-style);
}
</style>
<div class='test' on-tap='getStyle'>Hello</div>
</template>
</dom-module>
<script>
Polymer({
is: 'computed-style',
getStyle: function() {
console.log(this.getComputedStyleValue('--my-style'));
}
})
</script>
<computed-style></computed-style>

Simple stamped IF's in Polymer not working

I'm trying to build a simple component which will show a template based on a conditional.
If user.isAdmin is true then show the Admin Area, otherwise show the Guest Area.
For some reason none of the 2 template areas show up. What am I missing?
This is my component:
<dom-module id="custom-component">
<!--DOM-->
<template>
<template is="dom-if" if="{{!user.isAdmin}}">
Guest Area
</template>
<template is="dom-if" if="{{user.isAdmin}}">
Admin Area
</template>
</template>
<!--Scripts-->
<script>
Polymer({
is: 'custom-component',
properties: {
user: {"name":"Sample Name","isAdmin":true}
}
});
</script>
</dom-module>
Default values for properties may be specified in the properties object using the value field. The value may either be a primitive value, or a function that returns a value (which should be used for initializing Objects and Arrays to avoid shared objects on instances).
Source: https://www.polymer-project.org/1.0/docs/devguide/properties.html#configure-values
<!DOCTYPE html>
<html>
<head>
<base href="http://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
</head>
<body>
<dom-module id="unsupported-message">
<!--DOM-->
<template>
<template is="dom-if" if="{{!user.isAdmin}}">
Guest Area
</template>
<template is="dom-if" if="{{user.isAdmin}}">
Admin Area
</template>
</template>
<!--Scripts-->
<script>
Polymer({
is: 'unsupported-message',
properties: {
user: { // You'll have to declare your object properties this way
type: Object,
value: function() {
return {
"name": "Mr. Admin",
"isAdmin": true
};
}
}
}
});
</script>
</dom-module>
<unsupported-message></unsupported-message>
</body>
</html>

Polymer: Rendering looped JSON

I've seen a few answer to this but for some reason I can't wrap my head around why this isn't working. I'm trying to get the values of a JSON array and output them in custom HTML elements in my template.
Polymer Element:
<polymer-element name="graph-optionsLoad">
<template>
<core-ajax auto url="/getDataHeaders"
handleAs="json" response="{{headerList}}"></core-ajax>
<div>TEST</div>
<ul>
<template repeat="{{h in headerList}}">
<li> {{h}}</li>
</template>
</ul>
</template>
<script>
Polymer( "graph-optionsLoad", {
headerListChanged: function(oldValue) {
console.log(this.headerList);
// this.headers;
}
});
</script>
</polymer-element>
JSON:
{
"headers": [
"MakeSpawnFish",
"MakeEndGame",
"MakeModeChange",
"MakeConnectComponent",
"MakeCircuitCreated",
"MakeStartGame",
"MakeSnapshot",
"MakeResetBoard",
"MakeAddComponent",
"MakeCaptureFish",
"MakeRemoveComponent",
"MakeDisconnectComponent"
]
}
HTML
<!DOCTYPE html>
<html>
<head>
<script src="/static/bower_components/webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="/static/bower_components/my-elements/graph-optionsLoad.html">
<link rel="import" href="/static/bower_components/core-ajax/core-ajax.html">
<!-- <link rel="import" href="/static/greeting-tag.html"> -->
</head>
<body>
<graph-optionsLoad></graph-optionsLoad>
<script>
</script>
</body>
</html>
All that seems to show up on the page is the "TEST" and the empty <ul></ul>
I don't know if this helps. But I'll put it up just in case it helps someone else. In Polymer 1.0:
<dom-module id="graph-optionsload">
<template>
<iron-ajax auto
url="/getDataHeaders"
handle-as="json"
last-response="{{headerList}}"
on-response="listChanged"></iron-ajax>
<div>TEST</div>
<ul>
<template is="dom-repeat" items="[[headerList]]" as="[[h]]">
<li>[[h]]</li>
</template>
</ul>
</template>
<script>
Polymer({
id: "graph-optionsload",
properties: {
headerList: {type: Array, value: ()=>{return []}, notify: true}
},
listChanged: function(oldValue) {
console.log(this.headerList);
// this.headers;
}
});
</script>
</dom-module>
That should work for you.

Return simple value from polymer element?

I have successfully used core-ajax to pass a json object, but I want to write a custom element that can pass simple values. Here is what I have, but it is not working.
testOutput element
<link rel="import" href="../polymer/polymer.html">
<polymer-element name="testOutput">
<template>
This doesn't do anything but output a value.
</template>
<script>
Polymer('testOutput', {
response: "MyValue"
});
</script>
</polymer-element>
testInput element
<link rel="import" href="../polymer/polymer.html">
<polymer-element name="testInput" noscript attributes="input">
<template>
Here is the value from the other element:
<h1>{{input}}</h1>
</template>
</polymer-element>
index.html
<testOutput response="{{output}}"></testOutput>
<testInput input="{{output}}"></testInput>
output
This doesn't do anything but output a value.
Here is the value from the other element:
I simply had to publish the response variable in my output element. You can do this by including it in the attributes or using the publish function.
<polymer-element name="testOutput" attributes="response">
or
Polymer('testOutput', {
publish: {
response: "MyValue"
}
});
I think your response should be a function.
Polymer('testOutput', {
response: function() { return "MyValue" };
});
I think there are two ways to do it
First way
You need to create element where you want to get data:
<polymer-element name="first-element">
<template>
</template>
<script>
Polymer('first-element',{
needPass: 'I am Passed'
});
</script>
</polymer-element>
After you need to get first element using querySelector and get data
<link rel="import" href="../../bower_components/polymer/polymer.html">
<polymer-element name="second-element">
<template>
<style>
:host{
width: 100%;
height: 100%;
}
</style>
<h1>{{passed}}</h1>
</template>
<script>
Polymer('second-element',{
passed: '',
ready: function(){
var first_el = document.querySelector('first-element');
this.passed = first_el.needPass;
}
});
</script>
</polymer-element>
Than call the elements into your index
<first-element></first-element>
<second-element></second-element>
Second way
Or you can call first element into your second element
first element:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<polymer-element name="first-element" attributes="needPass">
<template>
</template>
<script>
Polymer('first-element',{
needPass: 'I am Passed'
});
</script>
</polymer-element>
second element
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="first-element.html">
<polymer-element name="second-element">
<template>
<style>
:host{
width: 100%;
height: 100%;
}
</style>
<first-element needPass="{{needPass}}"></first-element>
<h1>{{needPass}}</h1>
</template>
<script>
Polymer('second-element',{
ready: function(){
}
});
</script>
</polymer-element>
and call into index only second element
I hope it help for you.
PS: I tested the code.

Categories

Resources