Getting the value of a paper-radio-button inside a template - javascript

I have set up a template that pulls the headers from some data from a JSON file then creates a set of paper-radio-buttons from those headers. When I call this template (in a paper-shadow) I am having trouble capturing the value of the selected paper-radio-button when I click submit (in the paper-shadow).
Here's what is generated in the paper-shadow:
<polymer-element name="add-graphItem">
<template>
<div id="div" layout horizontal>
<paper-button raised class="colored" self-center>Upload File</paper-button>
<paper-input-decorator label="Enter URL for Dataset" floatingLabel error="A URL is required!" flex self-center>
<input is="core-input" id="graphSource" required>
</paper-input-decorator>
</div>
<div layout horizontal center-justified id="upload-options">
<paper-shadow class="card upload-options-box" z="1">
<core-header-panel flex id="graphHeaderList">
<core-toolbar class="upload-option-header">
<span flex>Variable</span>
</core-toolbar>
<graph-optionsLoadTest><graph-optionsLoadTest> <!-- this is where I call the paper-radio-button -->
</core-header-panel>
</paper-shadow>
<paper-shadow class="card upload-options-box" z="1">
<core-header-panel flex>
<core-toolbar class="upload-option-header top">
<span flex>Transform</span>
</core-toolbar>
<div class="upload-options">
<graph-functionsLoad><graph-functionsLoad> <!-- I also do another set here but I'm just working on the one for now since they do the same thing -->
</div>
</core-header-panel>
</paper-shadow>
</div>
<paper-button dismissive hover on-tap="{{cancelGraph}}">Cancel</paper-button>
<paper-button affirmative hover on-tap="{{addNewGraph}}">Submit</paper-button>
</template>
<script>
Polymer("add-graphItem",{
addNewGraph: function () {
console.log(this.$.headerValue.selectedItem);
var hValue = this.$.headerValue.selectedItem;
console.log(hValue);
},
cancelGraph: function () {
this.$.addGraph.toggle();
},
})
</script>
And here is the paper-radio-button template:
<link rel="import" href="/static/bower_components/core-ajax/core-ajax.html">
<polymer-element name="graph-optionsLoadTest">
<template>
<core-ajax auto url="/getDataHeaders"
handleAs="json" response="{{headerList}}"></core-ajax>
<paper-radio-group id="headerValue">
<template repeat="{{h in headerList.headers}}">
<paper-radio-button name='{{h}}' label='{{h}}'></paper-radio-button>
</template>
</paper-radio-group>
</template>
<script>
Polymer( "graph-optionsLoadTest", {
headerListChanged: function(oldValue) {
console.log(this.headerList);
// this.headers;
}
});
</script>
</polymer-element>
I've tried numerous ways to get the value of the selected paper-radio-group with no success, any help would be appreciated

Mike, I see a few issues that might help you.
First, you can only use the $ hash to access nodes defined with an id attribute in your template. To access other nodes, such as those defined dynamically or without an id attribute, you can use the querySelector method. This method also lets you search by selector (somewhat like JQuery). In addition, to access nodes within the shadow DOM of a Polymer component that do not have id attributes, you may use the shadowRoot member. These ideas are discussed in the Polymer documentation for Automatic Node Finding and, in more detail, in the section on Shadow DOM. (In addition, the closing tag for the <graph-optionsLoadTest> element is missing a /.)
The upshot is that in order to access a node within a nested component's shadow DOM, you need to use something either like
this.$.idOfgraphOptionsLoadTest.$.idOfRadioGroup, when you have defined id attributes for your elements;
this.shadowRoot.querySelector('graphOptionsLoadTest').shadowRoot.querySelector('paper-radio-group'), whether or not id attributes are defined; or
some combination of the two, when one component has ids and the other does not.
I would suggest giving the <graph-optionsLoadTest> element an id and using the first option above.
Example Code
Unfortunately, your code is rather difficult to use without the pieces that I surmise are hosting it. Therefore, I created the following to illustrate the principle:
<!doctype html>
<html>
<head>
<title>Home</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<script src="bower_components/webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="bower_components/paper-radio-button/paper-radio-button.html">
<link rel="import" href="bower_components/paper-radio-group/paper-radio-group.html">
</head>
<body unresolved fullbleed>
<polymer-element name="options-load" attributes="selected">
<template>
<paper-radio-group id="headerValue" selected="{{selected}}">
<template repeat="{{h in headerList.headers}}">
<paper-radio-button name='{{h}}' label='{{h}}' style="height: 100px"></paper-radio-button>
</template>
</paper-radio-group>
</template>
<script>
Polymer({
created: function() {
this.selected = 0;
this.headerList = {
headers: ['Option 1', 'Option 2', 'Option C']
};
}
});
</script>
</polymer-element>
<polymer-element name="add-graph-item">
<template>
<div layout horizontal around-justified>
<div>Options:</div>
<options-load id="optionsLoad"></options-load>
<button on-tap="{{doIt}}">Go</button>
<div>Results: </div>
<div id="results"></div>
</template>
<script>
Polymer({
doIt: function(event, detail, sender) {
var radioVal = this.$.optionsLoad.$.headerValue.selectedItem;
var msgTxt = 'Go clicked; ' + radioVal.label + ' selected'
console.log(msgTxt);
this.$.results.innerText = msgTxt;
}
});
</script>
</polymer-element>
<add-graph-item></add-graph-item>
</body>
</html>
Good luck!

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>

Is there an alternative to a bunch of dom-if's in Polymer?

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>

Polymer dom-module show nothing

i am new to polymer. So i just follow the tutorial. And i don't know why details in doesn't show on the screen.
this is the code from the net:
(index)
First poly
<body class:"vertical layout" style="background-color: #dddddd;">
<script src="components/webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="components/polymer/polymer.html">
<paper-header-panel>
<link rel="import" href="components/paper-material/paper-material.html">
<paper-material style="background: #ADADAD">
<link rel="import" href="first.html">
<first>
</first>
</paper-material>
</paper-header-panel>
</body>
</html>
(first)
<dom-module id="first">
<template>
<style>
div { color: red }
</style>
<div>Hello World</div>
</template>
<script>
Polymer ({ is : "first" });
</script>
</dom-module>
From the Polymer docs here
By specification, the custom element’s name must contain a dash (-).
Therefore your elements name first is invalid. Try renaming to my-element. I would also move your script and element imports into the <head> of the project.

How can I create a repeating element from data received from <iron-ajax>?

<iron-ajax auto
url='http://api.fantasy.nfl.com/v1/players/stats'
handle-as="json"
last-response="{{response}}"></iron-ajax>
<template is="dom-repeat" items="{{response}}">
<paper-material class="add-players">
<div class="layout horizontal center">
<h2>{{item.players.name}}</h2> //NOT SURE WHAT SYNTAX SHOULD BE
</div>
</paper-material>
</template>
I am using to return a response from a public API. The problem I have is that the API returns an object and Polymer does not allow us to do a dom-repeat over an object. I am really trying to access an array within that object, is there some way to extract that array from the object returned and do a dom-repeat over that array? If not is there another solution to accessing the response from polymer? Thank you!
You have to use {{response.players}} instead of {{response}} in the dom-repeat. Here is a working demo.
<!DOCTYPE html>
<html>
<head>
<title>paper-scroll-header-panel not working</title>
<script src="https://rawgit.com/webcomponents/webcomponentsjs/master/webcomponents.js"></script>
<base href="https://cdn.rawgit.com/download/polymer-cdn/1.0.1/lib/">
<link rel="import" href="iron-ajax/iron-ajax.html">
<link rel="import" href="paper-material/paper-material.html">
<!--<link rel="import" href="all-elements.html">-->
</head>
<body class="fullbleed">
<test-elem></test-elem>
<dom-module id="test-elem">
<template>
<iron-ajax auto
url='http://api.fantasy.nfl.com/v1/players/stats'
handle-as="json"
last-response="{{response}}"></iron-ajax>
<template is="dom-repeat" items="{{response.players}}">
<paper-material class="add-players">
<div class="layout horizontal center">
<h2>{{item.name}}</h2>
</div>
</paper-material>
</template>
</template>
<script>
Polymer({
is : "test-elem"
});
</script>
</dom-module>
</body>
</html>

Categories

Resources