Polymer dom-module show nothing - javascript

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.

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>

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

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!

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