The Polymer library is in maintenance mode. For new development, we recommend Lit.

You're viewing an older version of the Polymer library documentation. Please see Polymer 3.0 for the latest.

Polymer makes it simple to create web components, declaratively.

Custom elements can leverage Polymer's special features to reduce boilerplate and make it even easier to build complex, interactive elements:

  • Registering elements
  • Lifecycle callbacks
  • Property observation
  • Local DOM template
  • Data binding

In this section you can take a quick tour of the Polymer library, without installing anything. Click the Edit on Plunker button to open any of the samples in an interactive sandbox.

Tap the buttons following each feature to learn more.

To register a new element, call the Polymer function, which registers a new element with the browser. Registering an element associates a tag name with a prototype, so you can add properties and methods to your custom element. The custom element's name must contain a dash (-).

The Polymer function takes as an argument an object that defines your element's prototype.

proto-element.html
<link rel="import"  href="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/components/polymer/polymer.html">

<script>
  // register a new element called proto-element
  Polymer({
    is: "proto-element",

    // add a callback to the element's prototype
    ready: function() {
      this.textContent = "I'm a proto-element. Check out my prototype!"
    }
  });
</script>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/components/webcomponentsjs/webcomponents-lite.js"></script>
    <link rel="import" href="proto-element.html">
  </head>
  <body>
    <proto-element></proto-element>
  </body>
</html>

This sample uses a lifecycle callback to add contents to the <proto-element> when it's initialized. When a custom element finishes its initialization, the ready lifecycle callback is called. The ready callback is a great place to do constructor-like initialization work.

Learn more: element registration

Learn more: lifecycle callbacks

Many elements include some internal DOM nodes to implement the element's UI and behavior. Polymer calls this local DOM, and it provides an easy way to specify it:

dom-element.html
<link rel="import"  href="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/components/polymer/polymer.html">

<dom-module id="dom-element">

  <template>
    <p>I'm a DOM element. This is my local DOM!</p>
  </template>

  <script>
    Polymer({
      is: "dom-element"
    });
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit2.appspot.com/components/webcomponentsjs/webcomponents-lite.js"></script>
    <link rel="import" href="dom-element.html">
  </head>
  <body>
    <dom-element></dom-element>
  </body>
</html>

Local DOM is encapsulated inside the element.

Learn more: local DOM

Local DOM lets you control composition. The element's children can be distributed so they render as if they were inserted into the local DOM tree.

This example creates a simple tag that decorates an image by wrapping it with a styled <div> tag.

picture-frame.html
<link rel="import"  href="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/components/polymer/polymer.html">
<dom-module id="picture-frame">

  <template>
    <!-- scoped CSS for this element -->
    <style>
      div {
        display: inline-block;
        background-color: #ccc;
        border-radius: 8px;
        padding: 4px;
      }
    </style>
    <div>
      <!-- any children are rendered here -->
      <content></content>
    </div>
  </template>

  <script>
    Polymer({
      is: "picture-frame",
    });
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/components/webcomponentsjs/webcomponents-lite.js"></script>
    <link rel="import" href="picture-frame.html">
  </head>
  <body>
    <picture-frame>
      <img src="https://www.polymer-project.org/images/logos/p-logo-32.png">
    </picture-frame>
  </body>
</html>

Note: The CSS styles defined inside the <dom-module> are scoped to the element's local DOM. So the div rule here only affects <div> tags inside <picture-frame>.

Learn more: Composition & distribution

Of course, it's not enough to have static local DOM. You usually want to have your element update its local DOM dynamically.

Data binding is a great way to quickly propagate changes in your element and reduce boilerplate code. You can bind properties in your component using the "double-mustache" syntax ({{}}). The {{}} is replaced by the value of the property referenced between the brackets.

name-tag.html
<link rel="import"  href="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/components/polymer/polymer.html">

<dom-module id="name-tag">

  <template>
    <!-- bind to the "owner" property -->
    This is <b>{{owner}}</b>'s name-tag element.
  </template>

  <script>
  Polymer({
    is: "name-tag",
    ready: function() {
      // set this element's owner property
      this.owner = "Daniel";
    }
  });
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/components/webcomponentsjs/webcomponents-lite.js"></script>
    <link rel="import" href="name-tag.html">
  </head>
  <body>
    <name-tag></name-tag>
  </body>
</html>

Learn more: data binding

Properties are an important part of an element's public API. Polymer declared properties support a number of common patterns for properties—setting default values, configuring properties from markup, observing property changes, and more.

In the following example, we add a declared owner property with a default value, and configure it in index.html.

configurable-name-tag.html
<link rel="import"  href="https://polygit2.appspot.com/components/polymer/polymer.html">

<dom-module id="configurable-name-tag">

  <template>
    <!-- bind to the "owner" property -->
    This is <b>{{owner}}</b>'s configurable-name-tag element.
  </template>

  <script>
    Polymer({
      is: "configurable-name-tag",
      properties: {
        // declare the owner property
        owner: {
          type: String,
          value: "Daniel"
        }
      }
    });
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/components/webcomponentsjs/webcomponents-lite.js"></script>
    <link rel="import" href="configurable-name-tag.html">
  </head>
  <body>
    <!-- configure a property from markup by setting
         the corresponding attribute                 -->
    <configurable-name-tag owner="Scott"></configurable-name-tag>
  </body>
</html>

Learn more: declared properties

In addition to text content, you can bind to an element's properties (using property-name="{{binding}}"). Polymer properties can optionally support two-way binding.

This example uses two-way binding: binding the value of a custom input element (iron-input) to the element's owner property, so it's updated as the user types.

editable-name-tag.html
<link rel="import"  href="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/iron-*+polymerelements+^1.0.0/components/polymer/polymer.html">
<!-- import the iron-input custom element -->
<link rel="import" href="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/iron-*+polymerelements+^1.0.0/components/iron-input/iron-input.html">
<dom-module id="editable-name-tag">

  <template>
    <p>
    This is <strong>{{owner}}</strong>'s editable-name-tag.
    </p>
    <!-- iron-input exposes a two-way bindable input value -->
    <input is="iron-input" bind-value="{{owner}}"
      placeholder="Your name here...">
  </template>

  <script>
    Polymer({
      is: "editable-name-tag",
      properties: {
        owner: {
          type: String,
          value: "Daniel"
        }
      }
    });
  </script>

</dom-module>

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://polygit.org/polymer+^1.9.1/webcomponentsjs+^0.7.0/iron-*+polymerelements+^1.0.0/components/webcomponentsjs/webcomponents-lite.js"></script>
    <link rel="import" href="editable-name-tag.html">
  </head>
  <body>
    <editable-name-tag></editable-name-tag>
  </body>
</html>

Note: The is="iron-input" attribute indicates the input is a type-extension custom element; the element name is iron-input, and it extends the native <input> element.

Now that you understand these fundamental Polymer concepts: