npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@polymer/decorators

v3.0.0

Published

TypeScript decorators for Polymer

Downloads

3,923

Readme

NPM version Travis Build Status

polymer-decorators

A library of decorators to help you write web components with Polymer in TypeScript in a type safe and convenient way, like this:

import {PolymerElement} from '@polymer/polymer';
import {customElement, property} from '@polymer/decorators';

@customElement('my-element')
class MyElement extends PolymerElement {

  @property({type: String})
  myProperty: string = 'foo';
}

Contents

Installation

  1. Install the decorators with NPM.

    npm install --save @polymer/decorators
  2. Import decorators in your component definitions:

    import {customElement, property} from '@polymer/decorators';
  3. Enable the experimentalDecorators TypeScript compiler setting. Use the --experimentalDecorators flag, or update your tsconfig.json to include:

    {
      "compilerOptions": {
        "experimentalDecorators": true
      }
    }

Decorator reference

@customElement(tagname?: string)

Define a custom element.

If tagname is provided, it will be used as the custom element name, and will be assigned to the class static is property. If tagname is omitted, the static is property of the class will be used instead. If neither exist, or if both exist but have different values (except in the case that the is property is not an own-property of the class), an exception is thrown.

This decorator automatically calls customElements.define() with your class, so you should not include your own call to that function.

@customElement('my-element')
class MyElement extends PolymerElement {
  ...
}

@property(options?: PropertyObjects)

Define a Polymer property.

options is a Polymer property options object. All standard options are supported, except for value; use a property initializer instead. type is required, and must be one of the Polymer property constructor types (String, Object, etc.).

@property({type: String, notify: true})
foo: string = 'hello';

@computed(...targets: string[])

Define a computed property.

This decorator must be applied to a getter, and it must not have an associated setter.

Be sure to only read properties that you have declared as dependencies in the computed property definition, otherwise the computed property will not update as expected.

@computed('foo', 'bar')
get fooBar() {
  return this.foo + this.bar;
}

To define a computed property with more complex dependency expressions for which you may want to receive change values as arguments (e.g. sub-properties, splices, wildcards, etc.), or to set additional property options, define a standard property and set its computed option.

@property({computed: 'computeBaz(foo.*)', reflectToAttribute: true, type: String})
baz: string;

private computeBaz(fooChangeRecord: object) {
  ...
}

@observe(...targets: string[])

Define a complex property observer.

targets can be a single dependency expression, or an array of them. All observer dependency syntaxes are supported (property names, sub-properties, splices, wildcards, etc.).

@observe('foo', 'bar')
private fooBarChanged(newFoo: string, newBar: string) {
  console.log(`foo is now: ${newFoo}, bar is now: ${newBar}`);
}

@observe('baz.*')
private bazChanged(changeRecord: object) {
  console.log('baz changed deeply');
}

To define a simple property observer, which receives both the old and new values, set the observer option on the property you want to observe to the observer name or (preferably) function reference.

@property({observer: MyElement.prototype.bazChanged, type: String})
baz: string;

private bazChanged(oldValue: string, newValue: string) {
  console.log(`baz was: ${oldValue}, and is now: ${newValue}`);
}

@query(selector: string)

Replace this property with a getter that calls querySelector on the shadow root with the given selector. Use this to get a typed handle to a node in your template.

@query('my-widget')
widget: MyWidgetElement;

@queryAll(selector: string)

Replace this property with a getter that calls querySelectorAll on the shadow root with the given selector. Use this to get a typed handle to a set of nodes in your template.

@queryAll('my-widget')
widgets: NodeListOf<MyWidgetElement>

@listen(eventName: string, target: string|EventTarget)

Add an event listener for eventName on target. target can be an object reference, or the string id of an element in the shadow root. The method must match the signature (e: Event) => void, and must have public visibility.

Note that a target referenced by id must be defined statically in the top-level element template (e.g. not in a <dom-if>), because the $ id map is used to find the target upon ready().

To use @listen, your element must apply the DeclarativeEventListeners mixin, which is supplied with this package.

import {DeclarativeEventListeners} from '@polymer/decorators/lib/declarative-event-listeners.js';

class MyElement extends DeclarativeEventListeners(PolymerElement) {
  @listen('scroll', document)
  onDocumentScroll(event: Event) {
    this.scratchChalkboard();
  }
}

Note that to listen for Polymer gesture events such as tap and track, your element must also apply the GestureEventListeners mixin, which is supplied with Polymer.

import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {DeclarativeEventListeners} from '@polymer/decorators/lib/declarative-event-listeners.js';

class MyElement extends
    GestureEventListeners(
    DeclarativeEventListeners(
    PolymerElement)) {

  @listen('tap', 'red-button')
  onTapRedButton(event: Event) {
    this.launchMissile();
  }
}

FAQ

Do I need this library to use Polymer and TypeScript?

No, you can also use Polymer and TypeScript without any additional libraries. Polymer 3.0 ships with declarations to let you use the API with TypeScript directly. The advantage of using these decorators are additional type safety and convenience. For simple elements and applications, it may be preferable to use the vanilla Polymer API, like this:

import {PolymerElement, html} from '@polymer/polymer';

class MyElement extends PolymerElement {
  static get properties() {
    myProperty: String
  };

  static get template() {
    return html`<p>Hello World</p>`;
  }

  myProperty: string = 'foo';
}

customElements.define('my-element', MyElement);

What are the performance costs?

The additional JavaScript served for this library is approximately 2KB gzipped (0.6KB minified + gzipped). Benchmarks are not currently available, but we expect minor performance costs. The library generally works by building standard Polymer property definitions at element definition time, so performance costs should be seen at application startup.

Does it work with previous versions of Polymer?

An earlier version of this library can be used with Polymer 2.0, and installed with Bower. See the 2.x branch.

This library is not compatible with Polymer 1.0 or earlier, because it depends on the ES6 class-based component definition style introduced in Polymer 2.0. Community-maintained TypeScript decorator options for Polymer 1.0 include nippur72/PolymerTS and Cu3PO42/polymer-decorators.

What happened to Metadata Reflection support?

Support for the Metadata Reflection API was removed in version 3.0.0. This was done primarily because the type metadata emitted by TypeScript is often incorrect for our purpose (e.g. string|undefined produces Object instead of String), leading to unexpected bugs. Additionally, the required polyfill is fairly large (7KB gzipped), and standardization of the proposal does not currently appear to be progressing.