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.
Related
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);
}
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>
I'm trying to show an element based on an object type. For example, if the object type is 'string', paper-input should be displayed; if the type is 'boolean', paper-radio-group should be displayed, etc.
Below is a snippet of the component template.
<template is="dom-if" if="{{_isStringInput(question.input_type)}}">
<paper-input name="{{question.id}}" label="{{question.sort}}. {{question.text}}" always-float-label placeholder="{{question.help}}" required="{{question.required}}" error-message="Required" class="{{_isRequiredClass(question.required)}}"></paper-input>
</template>
<template is="dom-if" if="{{_isBooleanInput(question.input_type)}}">
<label>{{question.sort}}. {{question.text}}</label>
<paper-radio-group selected="" name="{{question.id}}" attr-for-selected="value" data-required="{{question.required}}">
<paper-radio-button name="{{question.id}}" value="yes">Yes</paper-radio-button>
<paper-radio-button name="{{question.id}}" value="no">No</paper-radio-button>
<p class="radio-error-message">Required</p>
</paper-radio-group>
</template>
As you can imagine, if I were to check for more types ('int', 'date', 'email', etc.), the dom-if list could grow bigger and bigger.
Is there a better/more elegant way to do this without a bunch of dom-if templates? (I'm thinking about something switch case vs. a bunch of if-else-ifs, but in Polymer)
I think these are the closest thing that Polymer has for that.
Dom-else
Dom-if-else
Can't find any if-else-if.
Here is an open enhancement issue on Github. Don't expect any such change from Polymer soon.
If you don't mind elements being just hidden instead of destroyed (which is opt-in with dom-if anyway), you can use CSS or hidden attribute to toggle visibility of your DOM
Using CSS classes to hide elements
The toggle function may be a little clunky but that's how you have to toggle using class. See below for an example with attributes.
Polymer({
is: 'toggle-element',
toggle: function() {
if(!this.disabled) {
this.disabled = 'disabled';
} else {
this.disabled = null;
}
}
});
<head>
<base href="https://polygit.org/components/" />
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import" />
</head>
<body>
<toggle-element></toggle-element>
<dom-module id="toggle-element">
<template>
<style>
.disabled {
display: none;
}
</style>
<button on-tap="toggle">Click to toggle</button>
<div class$="{{disabled}}">this will toggle</div>
</template>
</dom-module>
</body>
Using hidden attribute
This is a cleaner option but will work only with boolean properties.
Polymer({
is: 'toggle-element',
toggle: function() {
this.disabled = !this.disabled;
}
});
<head>
<base href="https://polygit.org/components/" />
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import" />
</head>
<body>
<toggle-element></toggle-element>
<dom-module id="toggle-element">
<template>
<button on-tap="toggle">Click to toggle</button>
<div hidden$="{{disabled}}">this will toggle</div>
</template>
</dom-module>
</body>
Using attributes and CSS to hide elements
Similar to the above but with attribute selector you can do anything that is possible with CSS and not being limited to hiding only (come think of it now, you can also style the hidden property, which Polymer uses by default. The principle is the same)
Polymer({
is: 'toggle-element',
toggle: function() {
this.disabled = !this.disabled;
}
});
<head>
<base href="https://polygit.org/components/" />
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import" />
</head>
<body>
<toggle-element></toggle-element>
<dom-module id="toggle-element">
<template>
<style>
[disabled] {
display: none;
}
div:not([disabled]) {
color: green;
}
</style>
<button on-tap="toggle">Click to toggle</button>
<div disabled$="{{disabled}}">this will toggle</div>
</template>
</dom-module>
</body>
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.
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>