FAQ
Thanks for checking us out! Polymer is still in developer preview.
Don’t see an answer to your question on here? Ask on the mailing list!
Table of contents
- Polymer
- Why should I care about this project?
- Is Polymer production ready?
- How is Polymer related to material design?
- Do I have to use Polymer Designer?
- I don’t like your {components | data binding syntax | face }!
- Which browsers does Polymer support?
- When will other browsers support these APIs natively?
- What’s your mobile story?
- How do I create a single page app with routing?
- What does this have to do with x-tags?
- How is Polymer different from Twitter’s Bootstrap or Adobe’s Topcoat?
- Is this project related to {Angular JS | Closure | Google Web Toolkit}?
- How is Polymer.dart related to Polymer?
- Is the code hosted on a CDN?
- I see a bunch of XHRs making network requests. What gives?
- Performance. Do you care about it?
- The filesize of webcomponents.js is big (~163KB). Why?
- Does Polymer work with Chrome Apps?
- Does Polymer work under Content Security Policy (CSP)?
- How can I contribute?
- Where is the best place to file bugs?
- How do I manage JavaScript dependencies to prevent 1000 copies of library X?
- What sort of testing do you do?
- How can I validate property values?
- Can an element
extend
from more than one element or have multiple inheritance? - I don’t like package managers, can’t I download Polymer as a zip?
- My components are producing markup with multiple ids of the same name.
- Data-binding
- Can I use
<template>
inside an<svg>
element? - Web Components
- How do I package a bunch of custom elements together?
- Crawlers understand custom elements? How does SEO work?
- Is there a registry of components I can play with?
- I get errors when trying to use
<link rel="import">
with external files. - Why does my element claim its
.clientWidth/clientHeight
is 0? - How do I access the DOM in a
<content>
? - Why do elements report zero (light DOM) children at created/ready time?
- When is the best time to access an element’s parent node?
- How do I monitor changes to light dom children?
- Can I use the
constructor
attribute without polluting the global namespace? - Does Shadow DOM play nicely with assistive technologies and screen readers?
- How do I access the
activeElement
inside a Polymer element? - Why don’t my element’s properties/methods autocomplete in the DevTools?
- What is the behavior of custom elements in a
<template>
?
Polymer
Why should I care about this project?
Polymer is a pioneering library that makes it faster and easier than ever before to build beautiful applications on the web. Polymer is built on top of a set of powerful new web platform primitives called Web Components. Web Components bring unprecedented composability, interoperability, and consumability to the web platform. The result is a monumental increase in developer productivity.
Is Polymer production ready?
Polymer is currently in “developer preview.” However, despite the label many people have already had success using Polymer in production. Although things might still change, we encourage developers to take Polymer out for a test drive.
How is Polymer related to material design?
Polymer is the embodiment of material design for the web. The Polymer team works closely with the design teams behind material design. In fact, Polymer played a key role in material design’s development: it was used to quickly prototype and iterate on design concepts. The material design components are still a work in progress, but will mature over the coming months.
Do I have to use Polymer Designer?
Nope! Polymer Designer is primarily a tool to make it easy to dive in and prototype apps. It’s entirely optional—although we’ve found that for developers who use it, it has quickly become an indispensable part of their workflow.
I don’t like your {components | data binding syntax | face }!
That’s fine. The cool thing about Web Components-based libraries like Polymer is that you can easily mix and match elements built using different libraries—and you don’t have to use any of our databinding syntax if you just want to use some of our elements.
Which browsers does Polymer support?
Polymer aims to support evergreen browsers. After all, we’re trying to simulate the future, and as someone once said, “You’re headed for trouble if all you do is stare in the rear-view mirror.” In practice, this means we support the most recent versions of Chrome, Safari, Internet Explorer, and Firefox. Chrome 36 is the first browser to ship all of the platform features Polymer depends on natively.
Note that this is fewer browsers than other frameworks support. For example, Polymer only aims to support Internet Explorer 10 and above. Some pieces of Polymer may support more browsers if it doesn’t require too much extra effort–if you find bugs in unsupported browsers, please still file them. Most things should work in IE9 today without too much work; feel free to file bugs on what doesn’t. IE8 is incompatable due to its insufficient DOM support.
See our Browser Compatibility page for more information.
When will other browsers support these APIs natively?
The foundation layer in our architecture diagram is based on emerging web standards. As browsers support them natively, the need for that layer will diminish and ultimately disappear. In fact, Chrome 36 is the first browser to support all of the primitives natively. It’s impossible to say when every browser will support these features natively–but the more that web developers ask for them, the sooner native support will come.
What’s your mobile story?
One of our core goals is for Polymer to work on modern mobile browsers as a first-class citizen. Check out Topeka, one of our sample apps, to see it in action.
How do I create a single page app with routing?
By combining data-binding, core-scaffold, core-pages/core-animated-pages, and <flatiron-director>
(an element for routing), you can easily create a responsive SPA with deep linking.
See customelements.io for further solutions.
What does this have to do with x-tags?
x-tags is a cool project that Mozilla is working on, and it’s not directly affiliated with Polymer. However, both Polymer and x-tags build on the emerging Custom Elements standard, which means their components are interoperable by default. Both Google and Mozilla offer polyfills for the Custom Element spec. X-Tag works on top of either, so you can use X-Tag custom elements alongside your Polymer components. We’re working actively with them to maximize compatibility between the component sets.
How is Polymer different from Twitter’s Bootstrap or Adobe’s Topcoat?
Bootstrap and Topcoat are awesome CSS/UI libraries. Our goals for Polymer are different. While we have our own set of shiny UI components, the meat of Polymer is geared towards developers interested in building web applications on top of Web Component technologies. Polymer also provides additional sugaring APIs to meet the demands of today’s web applications.
Is this project related to {Angular JS | Closure | Google Web Toolkit}?
Nope. Polymer isn’t like things that have come before. Polymer is the first of a new kind of library taking advantage of Web Components. The arrival of Web Components is a monumental change in web development, and we’re really excited about the future Polymer is demonstrating.
How is Polymer.dart related to Polymer?
polymer.dart is a Dart port of Polymer created and maintained by the Dart team. The Dart team is collaborating with the Polymer team to ensure that polymer.dart elements and polyfills are fully compatible with Polymer.
Is the code hosted on a CDN?
There is no official CDN version of Polymer. Some community members maintain a copy of Polymer on CloudFlare:
<script src="//cdnjs.cloudflare.com/ajax/libs/polymer/<version>/webcomponents.js"> <script src="//cdnjs.cloudflare.com/ajax/libs/polymer/<version>/polymer.js">
Where <version> is the latest version of Polymer available on CloudFlare.
There are a number of reasons why we recommend you use Bower instead of the CDN:
- The CDN does not host
polymer.html
which removes the ability for elements to import it. - There are many elements which are not hosted on the CDN so it might be tricky to include all of them in your project.
- You will not be able to Vulcanize your code.
For testing and reproducing bugs, you can link to the current versions of the webcomponents.js
and polymer.html
files on polymer-project.org
:
<script src="//www.polymer-project.org/0.5/components/webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="//www.polymer-project.org/0.5/components/polymer/polymer.html">
Many of the Core and Paper elements can also be found under components
.
Please do not use these URLs in production applications. They should only be used for testing and may break in the future!
I see a bunch of XHRs making network requests. What gives?
One limitation of today’s polyfills is that Polymer aggressively uses XHR to shim HTML Imports. We’re experimenting with packaging systems and build steps to reduce the cost of network requests. HTML imports are supported natively in Chrome 36 this API lands natively in browsers, where things will Just Work™. Resources load as they normally do, taking advantage of parallelism, browser caching, etc.
You can try Vulcanize, which is a build tool for concatenating a list of elements and inlining their definitions into your main page.
Performance. Do you care about it?
Deeply. And we want the entire web platform to be a buttery smooth 60fps. That said, we have not yet run benchmarks on the various polyfills–we’re in the early stages, after all! If you’re interested in helping us put some numbers behind these guys, let us know.
Remember our libraries go away over time! Polymer gets better, stronger, and faster as native browser implementations pop up.
The filesize of webcomponents.js is big (~163KB). Why?
Minified and gzipped, webcomponents.js is ~44KB (for comparison JQuery 1.10 is 32KB). Keep in mind that most of this size comes from the polyfills; code which has a death wish and goes away over time as browsers support the native APIs.
Polymer has also been designed to be a la carte. For example, if you’re only interested in Custom Elements, use the custom elements polyfill. If you only want Shadow DOM, use its polyfill. webcomponents.js is simply a convenient bundle for developers that includes all of the the pieces for building Polymer-based applications.
Does Polymer work with Chrome Apps?
Yes. Here’s an example Polymer Chrome App to get you started. It’s important to note that Chrome Apps have a strict Content Security Policy (CSP) which prevents the use of inline script elements. To handle the CSP limitation, this example uses our Vulcanize build tool (in the form of grunt-vulcanize) to turn inline script elements into external files. Be sure to read the FAQ section on Content Security Policy and the Dealing with CSP section in the sample project’s README.
Does Polymer work under Content Security Policy (CSP)?
Yes. By using webcomponents.js
and creating elements that use external scripts, Polymer runs under CSP. If you prefer to keep your element’s
script inline to <polymer-element>
, we recommend using Vulcanize and running with the --csp
flag.
In other nuanced cases, Polymer fails under CSP. This is because the HTML Imports is polyfilled using XHR, which can in turn, execute strings as JavaScript and fail CSP. So if you import a file that has an inline script tag, it will fail. This problem will go away with native HTML Imports (see Blink’s crbug.com/240592 tracking bug).
How can I contribute?
We love to hear your comments or suggestions. File a bug or swing by the mailing list and say “hi”–we don’t bite! If you want to contribute code, see our contributor’s guide.
Where is the best place to file bugs?
We have many different demo, platform, and library repositories. If you know exactly where the problem lives in the stack, please file the bug under the appropriate repo. Otherwise, filing under the general Polymer project is great.
How do I manage JavaScript dependencies to prevent 1000 copies of library X?
There is no way to guarantee sharing and deduping in the general case. However, if you have a library of components that use a library, they can all import a “library.html” file that loads that library. HTML Imports will de-dupe the import based on it’s fully qualified path.
If multiple libraries want to share a dependency, they will have to agree on a system. Feature detection, or an agreed upon common location for a ‘jquery.html’ file in a CDN, etc.
What sort of testing do you do?
Polymer uses Chromium’s continuous build infrastructure to test the entire system and each polyfill, individually.
How can I validate property values?
One way to validate input is to use a *Changed
handler to observe the
property changing, but separate out the “set value” vs. the “validated value”:
<polymer-element name="x-foo" attributes="color">
<template>
Do you like the color <span style="color:{{validColor}}">{{validColor}}</span>?
</template>
<script>
Polymer('x-foo', {
color: 'red',
colorChanged: function(inOld) {
if (this.color.match(/red|orange|yellow/)) {
this.validColor = this.color;
} else {
alert("The color wasn't a hot!");
}
}
});
</script>
</polymer-element>
<x-foo color="orange"></x-foo>
Can an element extend
from more than one element or have multiple inheritance?
For example <polymer-element name="my-element" extends="foo bar">
.
No. But Polymer may provide a syntax for mixins in the future.
I don’t like package managers, can’t I download Polymer as a zip?
Polymer has many different pieces. Creating a one-stop-shop .zip for all of the different permutations is unwieldy. If you really want a .zip, Github provides a download link on each project page. However in some cases, you won’t get the necessary dependencies and will need to do this on multiple repositories.
Web components and Polymer are intended to be extremely granular. This is on purpose, to allow users to use exactly what they need and nothing more. In additional to granularity, higher-level components may be composed out of lower-level components. Bower allows us to easily manage those dependencies.
My components are producing markup with multiple ids of the same name.
The Shadow DOM polyfill tries hard to mimic native Shadow DOM, in that nodes with the same
id
s will still be encapsulated.
However, you should avoid using DOM-level id referencing (e.g. <label for>
) when using
the polyfill. The id
may not resolve correctly when under the Shadow DOM polyfill.
Data-binding
I’m trying to render HTML using data-binding but Polymer escapes the content.
Polymer does not stamp unescaped HTML via data-binding because
it becomes a vulnerability for XSS attacks. For those cases where you need to
insert HTML with bindings after your element is created, Polymer
supplies the injectBoundHTML
method.
You can also use a property changed watcher
and automatic node finding to set the
.innerHTML
of an node:
<div id="div"></div>
dataChanged: function() {
this.$.div.innerHTML = this.data;
}
When using <template repeat>
, a similar approach can be taken as suggested in stackoverflow.com/a/22311788.
How do I use data-binding to repeat an <option>
or <tr>
?
Until the addition of HTML <template>
, certain elements like <select>
, <table>
, and others had special parser rules to prevent anything other than <option>
and <tr>
from being their children, respectively. Because of these legacy rules, browsers that don’t support <template>
will lift unexpected elements out of context and make them siblings, including <template>
itself!
For example, the following won’t work correctly in browsers that don’t support <template>
:
<!-- Won't work in browsers that don't support <template>. -->
<table>
<template repeat="{{tr in rows}}">
<tr><td>...</td></tr>
</template>
</table>
The <template repeat>
is hoisted out and rendered as a sibling:
<!-- Unsupported browsers make the child <template> a sibling. -->
<template repeat="{{tr in rows}}">
<tr><td>...</td></tr>
</template>
<table>
...
</table>
For browsers that don’t support <template>
, the TemplateBinding prollyfill has the ability to repeat <option>
and <tr>
directly using the template
attribute:
<table>
<tr template repeat="{{tr in rows}}">
<td>Hello</td>
</tr>
</table>
Another example using<select>
/<option>
:
<polymer-element name="my-select">
<template>
<select>
<option template repeat="{{options}}">{{}}</option>
</select>
</template>
<script>
Polymer('my-select', {
ready: function() { this.options = []; }
});
</script>
</polymer-element>
<script>
var select = document.createElement('my-select');
select.options = ['One', 'Two', 'Three'];
</script>
If your users are using browsers that don’t support <template>
, use the template
attribute on these special elements.
Note: browsers with native support for <template>
allow it to be a child
of elements <select>
and <table>
. If you know your users are using a browser
with support, write your repeaters like this:
<table>
<template repeat="{{tr in rows}}">
<tr>
<td>Hello</td>
</tr>
</template>
</table>
How can I access the current named model instance that in a <template repeat>
?
For example, in a on-*
handler, you can access the named model instance using: e.target.templateInstance.model.<property>
:
<polymer-element name="x-foo">
<template>
<template repeat="{{user in users}}">
<div on-click="{{clickHandler}}">{{user.name}}</div>
</template>
</template>
<script>
Polymer('x-foo', {
clickHandler: function(e, detail, sender) {
console.log(sender.templateInstance.model.user.name);
}
});
</script>
</polymer-element>
Can I use <template>
inside an <svg>
element?
Sure can. Here’s a demo.
<svg>
<template repeat="{{l in lights}}">
<circle cx="100" cy="{{l.cy}}" r="50" fill="{{l.selectedColor}}"/>
</template>
</svg>
The behavior is similar to templates in non-template browsers in that their content is not inert. For example, scripts will run.
How quickly are data changes propagated?
If Object.observe()
is available, data changes happen ~immediately at end of a microtask.
When Object.observe()
is not supported, Polymer uses its polyfill (observe-js) to poll and propagate data-changes throughout the system every 125ms.
Instead of waiting for the next poll interval, one can manually schedule an update
by calling Platform.flush()
. There are very few cases where you need to call Platform.flush()
directly.
Note: on platforms that support Object.observe()
natively, Platform.flush()
does nothing.
Web Components
How do I package a bunch of custom elements together?
Use a custom build step that flattens/concatenates everything into a single file,
then use HTML Imports (<link rel="import">
) to
bring that file into your app.
Similarly, you could write a build step that inlines any custom element definition directly into your main app. We’ve experimented with this basic idea in a tool we call Vulcanizer.
Crawlers understand custom elements? How does SEO work?
Because Polymer makes use of polyfills, search engines should treat Polymer-based applications no differently than they do other javascript-based web apps. In fact, Google’s crawler understands JavaScript heavy applications. Going forward, it is a reasonable assumption that as use of native Shadow DOM increases, search engine providers will try to adapt to understand it, just as they have adapted to other new web technologies in the past.
Is there a registry of components I can play with?
At http://customelements.io, you can find a growing registry of third party components and contribute yours too.
I get errors when trying to use <link rel="import">
with external files.
HTML Imports follow the same restrictions as XHR:
- URLs need to have an
http(s)
protocol. The browser imposes security restriction son what you can do withfile://
.- The resource needs to be CORs-enabled if it is remote to your server.
Why does my element claim its .clientWidth/clientHeight
is 0?
By default, customs elements are display: inline
. The fix is to give your element
a default style of display: block
using :host
.
<polymer-element name="my-element">
<template>
<style>
:host { display: block; }
</style>
...
</template>
...
</polymer-element>
<script>
window.addEventListener('polymer-ready', function(e) {
var element = document.querySelector('my-element');
// element.clientWidth/clientHeight won't be 0.
});
</script>
How do I access the DOM in a <content>
?
For a <content>
, you can iterate through content.getDistributedNodes()
to get the list of nodes distributed at the insertion point.
In Polymer, the best place to call this method is in the attached()
callback so you’re guaranteed that the element is in the DOM tree.
Also remember that you can access the light DOM as the element’s normal children
(i.e. this.children
, or other accessors). The difference with this approach
is that it’s the entire set of potentially distributed nodes; not those actually distributed.
Why do elements report zero (light DOM) children at created/ready time?
Because of subtle timing issues on element upgrades, it’s generally a mistake to attempt to reference an element’s children (light dom) in the created()
, ready()
, or attached()
method. When these methods are fired, the element is not guaranteed to be in the DOM or have children. In addition, Polymer calls TemplateBinding.createInstance()
on an element’s <template>
to create its Shadow DOM. This process creates and binds elements in the template one by one.
The best time to take a first look at an element’s children is in domReady()
. This is when the element is in the DOM, has a parent, its possibly children. To observe changes
to light DOM children, setup a mutation observer.
When is the best time to access an element’s parent node?
The attached()
callback is the best time to access an element’s parent.
That way, you’re guaranteed that the element is in DOM and its parent has been upgraded.
Use the attached()
and this.async()
to ensure you’re in the next quantum of time (e.g. the DOM has been constructed):
attached: function() {
this.async(function() {
// this.parentNode is upgraded
});
}
To manage this dance with more convenience, Polymer provides
domReady()
to do the same thing:
domReady: function() {
// same
}
How do I monitor changes to light dom children?
To know when light DOM children are added or removed, setup a Mutation Observer to do so. Polymer puts a onMutation
callback on every element which can be used to
observe a single DOM mutation:
ready: function() {
// Observe a single mutation.
this.onMutation(this, this.childrenUpdated);
},
childrenUpdated: function(observer, mutations) {
mutations.forEach(function(record) {
console.log(record.addedNodes);
}.bind(this));
}
To observe other types of changes, setup your own MutationObserver
in ready()
:
ready: function() {
var observer = new MutationObserver(function(mutations) {
...
}.bind(this));
observer.observe(this, {childList: true, attributes: true});
}
Can I use the constructor
attribute without polluting the global namespace?
By design, constructor
puts the constructor’s name on window
. If you don’t want
this, there are two options:
- Don’t use the
constructor
attribute. Usedocument.createElement()
instead. - Use
document.register()
and wrap the constructor it returns in a namespace.
Does Shadow DOM play nicely with assistive technologies and screen readers?
Note: Steve Faulkner had a nice writeup on this topic a while back and found that it does. See also Marcy Sutton’s more recent “Accessibility and the Shadow DOM”.
A common mis-conception is that the Shadow DOM doesn’t play nicely with assistive technologies. The reality is that the Shadow DOM can in fact be traversed and any node with Shadow DOM has a shadowRoot
property which points to it’s shadow document. Most assistive technologies hook directly into the browsers rendering tree, so they just see the fully composed tree.
In fact, if you inspect one of the native HTML elements that use Shadow DOM, <input type="date">
for example, you’ll notice aria attributes inside the tree:
Other types of assistive tools like Chromevox will need to be updated to learn how to traverse the Shadow DOM. There’s an ongoing discussion with accessibility experts on how best to integrate Shadow DOM with screen readers and search engines and further progress in this area is likely to come in the future.
How do I access the activeElement
inside a Polymer element?
Shadow Roots have their own activeElement
, which you can access internally as
shadowRoot.activeElement
.
Why don’t my element’s properties/methods autocomplete in the DevTools?
This is an artifact of the Shadow DOM polyfill. It creates wrappers around DOM elements
and exposes only the standard DOM APIs (e.g. querySelector
) on those wrappers. Polymer sets up properties on these wrapper objects, not on the actual DOM object. Since the DevTools
only knows about the actual DOM, your element properties won’t be seen by the tools.
Tip: select a node in the inspector can type wrap($0)
into the console. You’ll
get the wrapped node with all the Polymer goodies attached. You can also
use unwrap()
if you need to go the other direction.
Under native Shadow DOM this isn’t an issue. Properties will auto complete in the console.
What is the behavior of custom elements in a <template>
?
Custom elements in templates are like <script>
and friends–inert. Their definitions are registered but the elements are not upgraded. Upgrading elements in a <template>
would be a performance penalty.
Special thanks go to GitHub user md_5 who generously donated the Polymer organization name.