ce-decorators is a typescript library for custom element development. It is powered by lit-html for effective DOM updates. The decorator API is similar to stenciljs but without the need of a special compiler, just the ts-compiler is needed.
The decorators will take care of style registering if the ShadyCSS scoping shim is needed, attribute-property reflection with type transformation from attribute to property and vice versa. All in just 14kb (26kb with lit-html bundled).
Custom elements are user defined HTML elements, which offer customized functionalities and styling. When used inide an HTML template it looks like this:
Click this Button
In this example
custom-button is the tag-name of the element, primary is a specific attribute and Click this button is a slot element passed in the element for further processing.
For detailed information about custom elements see
The library is compatible with IE11 (needs babel transpile), Chrome, FF, Edge, Safari and the mobile Safari and Chrome Browser.
For IE11 you need:
@webcomponents/webcomponentsjs polyfills and Polyfills for
WeakMap and Promises
For Edge you need:
in FF, Safari and Chrome everything should just work.
If you compile all down to ES5 you need for all Brwosers the
- No boilerplate code
- Code completion since all properties are named and have types
npm install ce-decorators
important! you need the following compiler settings in your tsconfig.json
"emitDecoratorMetadata": true,"experimentalDecorators": true
babel dependencies (for ES5):
"@babel/plugin-proposal-class-properties": "^7.0.0","@babel/plugin-proposal-decorators": "^7.0.0","@babel/preset-env": "^7.0.0","@babel/preset-typescript": "^7.0.0", (optional only when using typescript)
plugins:"@babel/plugin-proposal-decorators" legacy: true/false"@babel/plugin-proposal-class-properties" "loose" : true
Both decorator specification (Stage-0 and Stage-2 are supported).
If decorators are used with babel the data type for the Prop decorator has to be specified, otherwise attribute reflection won't work.
- constructor call
- resolve promise returned by waitForConstruction() on custom element (awaitable)
- <append to dom>
- <if a property changed or first connect deferred in microtask (in asnyc task if you use
- componentWillRender(): property changes within this function will be taken into account in the rendering step
- componentDidRender(): can be used for post-processing runs in the same asnyctask/microtask as render
- resolve promise returned by waitForRender() on custom element (awaitable)
- <if property or attribute changed (deferred in microtask)>
- render() deferred in microtask or in asnyc task if you use
- <remove/detach from dom>
;await element.waitForForConstruction;element.propertyOne = 'test'; // will be reflected as property-one attributedocument.querySelector'body'.appenChildelement;// element.componentConnected() calledawait element.waitForRender;// element.componentWillRender() called// element.render() called// element.componentFirstRender() called *only called on first render*// element.componentDidRender() calleddocument.querySelector'body'.removeChildelement;// element.componentDisconnected() called
Because render calls are deferred into a microtask or async task, setting multiple attributes/properties consecutively will result in just one render call.
- set property myProperty
- run interceptors
- if reflectToAttribute is set for myProperty (or undefined, which is the default case), the property will be reflected as attribute my-property
- notify watchers
- deffer render() to microtask (so if multiple attributes/properties are set in the same task, render is only called once)
LazyCustomElement is an alternative to the default
CustomElement which renders in an asnyc task (
setTimeout) instead of a microtask .
Use with Angular
CUSTOM_ELEMENTS_SCHEMA needs to be activated. Now custom elements can be used like angular components.
in the component:
in the template:
Use with react
In react you need to pass everything as attributes