Understanding the constructor attribute in Polymer elements - polymer

A Polymer noob...
I'm trying to create a custom element as per the Polymer API docs, where my main page looks like this:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Polymer</title>
<script src="bower_components/platform/platform.js"></script>
<link rel="import" href="bower_components/polymer/polymer.html">
</head>
<body>
<div id="test"></div>
<polymer-element name="book-template" constructor="BookTemplate" noscript>
<template>
<style>
h1 { color: orange; }
</style>
<h1>Hello from some-foo</h1>
</template>
</polymer-element>
</body>
</html>
I know that the page content will render if I just put <book-template></book-template> on the page, or if I do something like this inside the <body> tag:
<script>
var book = document.createElement('book-template');
document.getElementById('test').appendChild(book);
</script>
But I'm trying to utilize the element's constructor attribute, assuming that this will create the element when placed somewhere inside of <body>:
<script>
var book = new BookTemplate();
</script>
...but getting a console message that BookTemplate() is not defined.
I'm sure it's something simple...any idea? Thanks in advance.

I guess you have to wait for the polymer-ready event, so that the constructor is available in the global window object http://jsbin.com/kosuf/2/edit?html,console,output:
<script>
document.addEventListener('polymer-ready',function() {
var book = new BookTemplate();
if (book) {
console.log('Ok');
}
});
</script>

Related

reading json and converting to HTML - polymer

I am trying to read local json file and convert it to HTML layout
I was able to read JSON from local but struggling to read and render on UI
HTML:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.rawgit.com/download/polymer-cdn/1.5.0/lib/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.5.0/lib/polymer/polymer.html">
<link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.5.0/lib/iron-ajax/iron-ajax.html">
</head>
<body>
<template is="dom-bind">
<iron-ajax
auto
url="properties.json"
last-response="{{data}}"
handle-as="json">
</iron-ajax>
<div><span>{{data}}</span></div>
<!-- <template is="dom-repeat" items="{{data}}">
<div><span>{{item.name}}</span></div>
</template> -->
</template>
<script>
(function (document) {
'use strict';
var app = document.querySelector('#app');
window.addEventListener('WebComponentsReady', function() {
var ironAjax = document.querySelector('iron-ajax');
ironAjax.addEventListener('response', function() {
console.log(ironAjax.lastResponse);
});
ironAjax.generateRequest();
});
})(document);
</script>
</body>
</html>
properties.json file
{
"main":{
"header":{
"label" :"Employee Template",
"logo":"abc.png"
},
"footer":{
"label" :"2017 All rights reserved.",
"author":"abc"
},
"menu":[
{
"label":"Add",
"url":"/Add"
},
{
"label":"Delete",
"url":"/Delete"
}
]
}
I am trying to render the above json as below HTML
<header><h1>{{Employee.header.label}}</h1>
<img src={{Employee.header.logo}}>
</header>
<ul>
<li>{{Employee.menu[0].label}}</li>
<li>{{Employee.menu[0].label}}</li>
</ul>
<footer><h1>{{Employee.footer.label}}</h1>
<div>{{Employee.footer.author}}></div>
</footer>
I tried iron-ajax for rendering, but it works only on array of objects and not reading through the json and didnt find much information on documentation
At first, you are propably missing main in all bindings? according to your json the hiearchy is main.header.label and not header.label.
Another issue: When you are pointing to some index of array in bindings you are using {{Employee.menu[0].label}} but it should be {{Employee.menu.0.label}}. Remember this, because once you will use array mutation methods, it will be same.
If your JSON's structure is always like that and never changes, then it's super simple and you have already did, what you wanted. If your JSON's structure can change to something more complex, then you will have to propably write your own parser. which means, iterating all keys insinde json, creating elements and putting content in it. It will be a little bit harder, but it is possible.
I don't know how your json can look like so i won't write you parser. You will have to try it on your own.
It will start something like:
for(var key in this.Employee.main) {
var el = document.createElement(key);
...
}
here is an fiddle with an working example of your code: fiddle
The fiddle is ab bit different since i have no clue how to do ajax in fiddle but your code sould look like this:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.rawgit.com/download/polymer-
cdn/1.5.0/lib/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="https://cdn.rawgit.com/download/polymer-
cdn/1.5.0/lib/polymer/polymer.html">
<link rel="import" href="https://cdn.rawgit.com/download/polymer-
cdn/1.5.0/lib/iron-ajax/iron-ajax.html">
</head>
<body>
<template is="dom-bind">
<iron-ajax
auto
url="properties.json"
last-response="{{data}}"
handle-as="json">
</iron-ajax>
<header><h1>{{Employee.header.label}}</h1>
<img src={{Employee.header.logo}}>
</header>
<ul>
<li>{{data.main.menu.0.label}}</li>
<li>{{data.main.menu.0.label}}</li>
</ul>
<footer><h1>{{data.main.footer.label}}</h1>
<div>{{data.main.footer.author}}></div>
</footer>
</template>
<script>
(function (document) {
'use strict';
var app = document.querySelector('#app');
window.addEventListener('WebComponentsReady', function() {
var ironAjax = document.querySelector('iron-ajax');
ironAjax.addEventListener('response', function() {
console.log(ironAjax.lastResponse);
});
ironAjax.generateRequest();
});
})(document);
</script>
</body>
</html>`

how to render a raised paper-button with reactjs?

Here is the code that should render a "raised" paper-button:
All the code is in a script tag and renders a paper-button that is not RAISED (see screen shot). I can click and see the RIPPLE effect, seems perfect except the appearance.
UPDATE :
for the moment the only way to get the correct rendering is by replacing
<paper-button raised>test</paper-button>
BY
<div dangerouslySetInnerHTML={{__html: '<paper-button raised>test</paper-button>'}} />
ANY WORKAROUND avoiding this 'dangerous' way?
<!DOCTYPE html>
<html>
<head>
<script src="bower_components/webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/paper-button/paper-button.html">
<title>Hello React</title>
<script src="bower_components/react/react.min.js"></script>
<script src="bower_components/react/JSXTransformer.js"></script>
</head>
<body>
<div id="content">
</div>
<script type="text/jsx">
var ButtonT = React.createClass({
render: function() {
return (
<div>
<paper-button raised="true">test</paper-button>
</div>
);
}
});
React.render(
<ButtonT />,
document.getElementById('content')
);
</script>
</body>
</html>
Should the "raised" attribute be passed as a this.props...?
It won't work in the current version of React. Custom attribute support is an open issue, though. For now, I've found this patch works well.
In JSX if you want a custom HTML attribute, you should prefix it with data-, it then will be resolved to actual name without prefix. See docs;

Polymer preload spinner

Sometimes it takes a while for polymer to load, and when using <body unresolved>, the page stays blank until everything is ready. Is there a way to display something between the time that the page is served and the time that polymer is done doing its magic?
The documentation that describes the unresolved attribute clears some of this up.
While it's common to apply unresolved to the <body> element, causing the entirety of your page's content to be hidden until Polymer is ready, it can be applied to any element(s). You can, for instance, use <div unresolved> as a wrapper around the portion of your page that relies on Polymer, and create a loading message that's outside that wrapper which will be visible immediately. (You'd then want to listen to the polymer-ready event and hide your loading message when that's fired.)
Here's an example using a very contrived way of slowing down the time it takes for the Polymer element to complete one of its lifecycle methods (live demo):
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Polymer Demo</title>
<style>
.hidden {
display: none;
}
</style>
</head>
<body>
<p id="spinner">Loading...</p>
<script src="http://www.polymer-project.org/platform.js"></script>
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<polymer-element name="slow-poke">
<template>
<h1><content></content></h1>
</template>
<script>
Polymer({
// Used to introduce a delay in initializing the Polymer element.
// Don't try this at home!
created: function() {
var start = Date.now();
while (true) {
if (Date.now() - start > 1000) {
break;
}
}
}
});
</script>
</polymer-element>
<div unresolved>
<slow-poke>Here I am... finally!</slow-poke>
<slow-poke>Me too!</slow-poke>
</div>
<script>
window.addEventListener('polymer-ready', function() {
document.querySelector('#spinner').classList.add('hidden');
});
</script>
</body>
</html>
(By the way, what are you finding to be slow-loading? If it's a standard/core element, it might be worth filing a bug against the corresponding project on GitHub.)

Uncaught ReferenceError: Polymer is not defined after event.preventDefault()

I am getting the following error:
Uncaught ReferenceError: Polymer is not defined
when I click on the link on the following element:
<!DOCTYPE html>
<html>
<head>
<script src="bower_components/platform/platform.js"></script>
</head>
<body>
<my-element id="my_element"></my-element>
</body>
</html>
<link rel="import" href="bower_components/polymer/polymer.html">
<polymer-element name="my-element">
<template>
my link
</template>
<script>
Polymer('my-element', {
linkClicked: function(event, detail, sender) {
event.preventDefault();
}
});
</script>
</polymer-element>
Is this a Polymer bug or am I doing something wrong?
http://jsbin.com/cuxep/1/edit?html,output
As #badsyntax points out above, it looks like event.preventDefault() doesn't work well for the tap event. Changing to on-click seems to solve the problem of preventing a navigation though.
The error that you saw:
Uncaught ReferenceError: Polymer is not defined
That seems to be an artifact of malformed HTML, I suspect this was causing a race condition between loading polymer.html and your <script> element being executed. After cleaning up the HTML I was no longer able to reproduce it.
Here's a jsbin that works as I believe you intend: http://jsbin.com/boweliwe/1/edit
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<script>console.clear()</script>
<script src="//www.polymer-project.org/components/platform/platform.js"></script>
<link rel="import" href="//www.polymer-project.org/components/polymer/polymer.html">
<my-element></my-element>
<polymer-element name="my-element">
<template>
my link
</template>
<script>
Polymer('my-element', {
linkClicked: function(event, detail, sender) {
event.preventDefault();
}
});
</script>
</polymer-element>
</body>
</html>

Extending dart:html class "ButtonElement" in Dart

I tried to extend a <button>, but so far did not succeed.
What am I doing wrong. I'm using the Dart Editor+SDK 1.5.2
In pubspec.yaml the version for Polymer is set to:
polymer: ">=0.11.0 <0.12.0"
index.html
<!DOCTYPE html>
<html>
<head>
<!-- <script src="packages/web_components/platform.js"></script>
not necessary anymore with Polymer >= 0.14.0 -->
<script src="packages/web_components/dart_support.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Extended Button - Dart v1.5.2</title>
<!--Extended Button-->
<link rel="import" href="view/ext_button.html" />
</head>
<body>
<button is="ext-button">Test Button</button>
<script type="application/dart">export "package:polymer/init.dart";</script>
</body>
</html>
view/ext_button.dart
import "dart:html";
import "package:polymer/polymer.dart";
#CustomTag("ext-button")
class ExtButton extends ButtonElement {
ExtButton.created() : super.created();
factory ExtButton(){
onClick.listen(clicked);
}
void clicked(MouseEvent e){
print("Ext-Button clicked");
}
}
view/ext_button.html
<!DOCTYPE html>
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="ext-button" extends="button">
<template>
</template>
<script type="application/dart" src="ext_button.dart"></script>
</polymer-element>
So the code above does not work, but as soon as write it like below (just to validate the ext-button works) it tells me the following:
"web/index.html:20:7: custom element "ext-button" extends from "button", but this tag will not include the default properties of "button".
To fix this, either write this tag as <button is="ext-button"> or remove the "extends" attribute from the custom element declaration."
<ext-button>Test Button</ext-button>
So a little bit confused ;-) I think the fix is easy and simple - but I just don't see the problem ;-(
Just for further references, the two things above solved the problem.
Here are the updated parts, now it works.
view/ext_button.dart
import "dart:html";
import "package:polymer/polymer.dart";
#CustomTag("ext-button")
class ExtButton extends ButtonElement with Polymer {
ExtButton.created() : super.created()
{
polymerCreated();
onClick.listen(clicked);
}
void clicked(MouseEvent e){
print("Ext-Button clicked");
}
}
view/ext_button.html
<!DOCTYPE html>
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="ext-button" extends="button">
<template>
<content></content>
</template>
<script type="application/dart" src="ext_button.dart"></script>
</polymer-element>
As far as I see, you are missing thwo things:
a call to polymerCreated() inside the custom elements constructor.
and extends ButtonElement with Polymer
There are already similar question. I'll look them up later when I have more time. Maybe you find them yourself in the meantime. Please add a comment with a link if you do.