Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Document inferred name in Polymer() #530

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 112 additions & 35 deletions docs/polymer/polymer.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,21 @@ At the heart of {{site.project_title}} are [Custom Elements](/platform/custom-el
<template>
<!-- shadow DOM here -->
</template>
<script>Polymer('tag-name');</script>
<script>
Polymer({
// properties and methods here
});
</script>
</polymer-element>

The element declaration includes:

- The `name` attribute specifies the name of the new custom element.
- The optional `<template>` tag defines HTML content that is
cloned into the shadow DOM of each instance of the element.
- The `Polymer` method, which _registers_ the element, so it's
recognized as a custom element by the browser.

### Attributes

{{site.project_title}} reserves special attributes to be used on `<polymer-element>`:
Expand All @@ -41,7 +53,7 @@ At the heart of {{site.project_title}} are [Custom Elements](/platform/custom-el
<td><code>extends</code></td><td>optional</td><td>Used to <a href="#extending-other-elements">extend other elements</a>.</td>
</tr>
<tr>
<td><code>noscript</code></td><td>optional</td><td>For simple elements that don't need to call <code>Polymer()</code>. See <a href="#altregistration">Alternate ways to register an element</a>.</td>
<td><code>noscript</code></td><td>optional</td><td>For simple elements that don't need to call <code>Polymer()</code>. See <a href="#altregistration">Element registration</a>.</td>
</tr>
<tr>
<td><code>constructor</code></td><td>optional</td><td>The name of the constructor to put on the global object. Allows users to create instances of your element using the <code>new</code> operator (e.g. <code>var tagName = new TagName()</code>).</td>
Expand All @@ -55,7 +67,7 @@ on each instance of the element. For example:

<polymer-element name="tag-name" class="active" mycustomattr>
<template>...</template>
<script>Polymer('tag-name');</script>
<script>Polymer();</script>
</polymer-element>

When an instance of `<tag-name>` is created, it contains `class="active" mycustomattr`
Expand All @@ -79,11 +91,43 @@ This also means that any of the below examples will also work:
<name-tag NAMECOLOR="red" name="Red Name"></name-tag>
<name-tag NAMEcolor="green" name="Green Name"></name-tag>

### Alternate ways to register an element {#altregistration}


### Element registration {#altregistration}

The `Polymer` method is used to register an element:

<pre>
Polymer(<em class="nocode">tag-name</em>, <em class="nocode">proto-object</em>);
</pre>

Where:

* _tag-name_ matches the `name` attribute in the `<polymer-element>` tag.
_tag-name_ is **optional** as long as **the `<script>` tag that calls `Polymer`
is placed inside the `<polymer-element>` tag.**

* _proto-object_ defines properties and methods to add to the
elements prototype. See [Adding public properties and methods](#propertiesmethods).
_proto-object_ is always optional.

The simplest way to invoke `Polymer` is to place an inline script inside
your `<polymer-element>` tag:

<polymer-element name="simple-tag">
<script>Polymer();</script>
</polymer-element>

There are several alternative ways to register elements:

- [Separating script from markup](#separatescript).
- [Registering imperatively](#imperativeregister) using JavaScript.

#### Separate script from markup {#separatescript}

For convenient decoupling of script and markup, you don't have to inline your script.
{{site.project_title}} elements can be created by referencing an external script
which calls `Polymer('tag-name')`:
which calls `Polymer`:

<!-- 1. Script referenced inside the element definition. -->
<polymer-element name="tag-name">
Expand All @@ -97,16 +141,31 @@ which calls `Polymer('tag-name')`:
<template>...</template>
</polymer-element>

In case #2, where the script is invoked before the `<polymer-element>` tag,
the call to `Polymer` **must include the tag name**:

// tagname.js
Polymer('tag-name', ... );

For elements that don't require custom properties or methods, you can
use the `noscript` attribute:

<!-- 3. No script -->
<polymer-element name="tag-name" constructor="TagName" noscript>
<template>
<!-- shadow DOM here -->
</template>
</polymer-element>

The `noscript` attribute is equivalent to including:

<script>
Polymer();
</script>

#### Imperative registration {#imperativeregister}

Elements can be registered in pure JavaScript like so:
Elements can be registered in pure JavaScript like this:

<script>
Polymer('name-tag', {nameColor: 'red'});
Expand All @@ -124,22 +183,30 @@ Elements can be registered in pure JavaScript like so:

<name-tag name="John"></name-tag>

Note that you need to add the `<polymer-element>` to the document so that the
You need to add the `<polymer-element>` to the document so that the
Custom Elements polyfill picks it up.

**Important:** Since the `Polymer` call here is outside the `<polymer-element>`,
it must include the tag name argument.
{: .alert .alert-error }

### Adding public properties and methods {#propertiesmethods}

If you wish to define methods/properties on your element (optional), pass an object
as the second argument to `Polymer()`. This object is used to define
the element's `prototype`.
To define methods/properties on your element, pass an object argument to `Polymer()`:

<pre>
Polymer([ <em class="nocode">tag-name</em>, ] <em class="nocode">proto-object</em>);
</pre>

The _proto-object_ contains properties and methods to add to the element's `prototype`.

The following example defines a property `message`, a property `greeting`
using an ES5 getter, and a method `foo`:

<polymer-element name="tag-name">
<template>{{greeting}}</template>
<script>
Polymer('tag-name', {
Polymer({
message: "Hello!",
get greeting() {
return this.message + ' there!';
Expand All @@ -152,7 +219,17 @@ using an ES5 getter, and a method `foo`:
**Note:** `this` references the custom element itself inside a {{site.project_title}} element. For example, `this.localName == 'tag-name'`.
{: .alert .alert-info }

A custom element's prototype is assembled in this order:

- The base prototype is copied from the DOM object that the custom element extends (by default, `HTMLElement`).
- {{site.project_title}} adds a set of built-in methods and properties (see [Built-in element methods](#builtin)).
- The properties and methods defined in the _proto-object_ are added into the element's prototype.

Avoid defining a property or method with the same name as a native DOM property or method, such as `id`, `children`,
`focus`, `title` and `hidden`; the results are unpredictable.

**Important:** Be careful when initializing properties that are objects or arrays. Due to the nature of `prototype`, you may run into unexpected "shared state" across instances of the same element. If you're initializing an array or object, do it in the `created` callback rather than directly on the `prototype`.
{: .alert .alert-error }

// Good!
Polymer('x-foo', {
Expand All @@ -177,11 +254,11 @@ techniques like anonymous self-calling functions:
<template>...</template>
<script>
(function() {
// Ran once. Private and static to the element.
// Run once. Private and static to the element.
var foo_ = new Foo();

// Ran for every instance of the element that's created.
Polymer('tag-name', {
// Run for every instance of the element that's created.
Polymer({
get foo() { return foo_; }
});
})();
Expand All @@ -202,7 +279,7 @@ To achieve this, you can use the [MonoState Pattern](http://c2.com/cgi/wiki?Mono
var firstName = 'John';
var lastName = 'Smith';

Polymer('app-globals', {
Polymer({
ready: function() {
this.firstName = firstName;
this.lastName = lastName;
Expand All @@ -221,7 +298,7 @@ Then use the element as you would any other, and data-bind it to a property that
<div id="lastname">{{globals.lastName}}</div>
</template>
<script>
Polymer('my-component', {
Polymer({
ready: function() { this.globals = this.$.globals; }
});
</script>
Expand All @@ -234,7 +311,7 @@ A slight tweak of this approach lets you configure the value of the globals exte
(function() {
var values = {};

Polymer('app-globals', {
Polymer({
ready: function() {
this.values = values;
for (var i = 0; i < this.attributes.length; ++i) {
Expand Down Expand Up @@ -338,15 +415,15 @@ As an example, here's an element that publishes three public properties, `foo`,

<polymer-element name="x-foo" attributes="foo bar baz">
<script>
Polymer('x-foo');
Polymer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, we should leave all these examples as it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I wasn't really sure what to do with them. I thought Scott wanted to highlight this more, but I'd be happy to revert these -- @sjmiles?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind; reverted examples.

</script>
</polymer-element>

And here's one using the `publish` object:

<polymer-element name="x-foo">
<script>
Polymer('x-foo', {
Polymer({
publish: {
foo: 'I am foo!',
bar: 5,
Expand Down Expand Up @@ -382,7 +459,7 @@ By default, properties defined in `attributes` are initialized to `null`:
<polymer-element name="x-foo" attributes="foo">
<script>
// x-foo has a foo property with default value of null.
Polymer('x-foo');
Polymer();
</script>
</polymer-element>

Expand All @@ -392,7 +469,7 @@ You can provide your own default values by explicitly specifying the default val

<polymer-element name="x-foo" attributes="bar">
<script>
Polymer('x-foo', {
Polymer({
// x-foo has a bar property with default value false.
bar: false
});
Expand All @@ -403,7 +480,7 @@ Or you can define the whole thing using the `publish` property:

<polymer-element name="x-foo">
<script>
Polymer('x-foo', {
Polymer({
publish: {
bar: false
}
Expand All @@ -417,11 +494,11 @@ created for each instance of the element:

<polymer-element name="x-default" attributes="settings">
<script>
Polymer('x-default', {
Polymer({
created: function() {
// create a default settings object for this instance
this.settings = {
textColor: 'blue';
textColor: 'blue'
};
}
});
Expand Down Expand Up @@ -478,7 +555,7 @@ includes an unlikely combination of all three:

<polymer-element name="hint-element" attributes="isReady items">
<script>
Polymer('hint-element', {
Polymer({

// hint that isReady is a Boolean
isReady: false,
Expand Down Expand Up @@ -549,7 +626,7 @@ For example:

<polymer-element name="disappearing-element">
<script>
Polymer('disappearing-element', {
Polymer({
publish: {
hidden: {
value: false,
Expand Down Expand Up @@ -589,7 +666,7 @@ For example, we can define a `name-tag` element that publishes two properties,
Hello! My name is <span style="color:{%raw%}{{nameColor}}{%endraw%}">{%raw%}{{name}}{%endraw%}</span>
</template>
<script>
Polymer('name-tag', {
Polymer({
nameColor: "orange"
});
</script>
Expand Down Expand Up @@ -640,7 +717,7 @@ It uses special <code>on-<em>event</em></code> syntax to trigger this binding be
<button on-click="{% raw %}{{buttonClick}}{% endraw %}"></button>
</template>
<script>
Polymer('g-cool', {
Polymer({
keypressHandler: function(event, detail, sender) { ...},
buttonClick: function(event, detail, sender) { ... }
});
Expand Down Expand Up @@ -668,7 +745,7 @@ All properties on {{site.project_title}} elements can be watched for changes by

<polymer-element name="g-cool" attributes="better best">
<script>
Polymer('g-cool', {
Polymer({
better: '',
best: '',
betterChanged: function(oldValue, newValue) {
Expand Down Expand Up @@ -783,7 +860,7 @@ For example, the following defines a component whose template contains an `<inpu
<input type="text" id="nameInput">
</template>
<script>
Polymer('x-form', {
Polymer({
logNameValue: function() {
console.log(this.$.nameInput.value);
}
Expand Down Expand Up @@ -823,7 +900,7 @@ Example:
<button on-click="{{onClick}}">Send hurt</button>
</template>
<script>
Polymer('ouch-button', {
Polymer({
onClick: function() {
this.fire('ouch', {msg: 'That hurt!'}); // fire(inType, inDetail, inToNode)
}
Expand Down Expand Up @@ -855,7 +932,7 @@ and data-bound.
You are {%raw%}{{praise}}{%endraw%} <content></content>!
</template>
<script>
Polymer('polymer-cool', {
Polymer({
praise: 'cool'
});
</script>
Expand All @@ -868,7 +945,7 @@ and data-bound.
<shadow></shadow> <!-- "You are cool Matt" -->
</template>
<script>
Polymer('polymer-cooler');
Polymer();
</script>
</polymer-element>

Expand All @@ -884,7 +961,7 @@ When you override an inherited method, you can call the parent's method with `th
You are {{praise}} <content></content>!
</template>
<script>
Polymer('polymer-cool', {
Polymer({
praise: 'cool',
makeCoolest: function() {
this.praise = 'the coolest';
Expand All @@ -899,7 +976,7 @@ When you override an inherited method, you can call the parent's method with `th
<shadow></shadow>
</template>
<script>
Polymer('polymer-cooler', {
Polymer({
praise: 'cool',
makeCoolest: function() {
this.super(); // calls polymer-cool's makeCoolest()
Expand Down