This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Adding web components utilities, meta-120 (#300)

* Adding web components utilities, meta-120
  • Loading branch information...
rorticus committed Jan 30, 2017
1 parent 8741d3b commit 137d28ffc98c556d017dbbc1c9344025a7acb691
Showing with 951 additions and 0 deletions.
  1. +144 −0 README.md
  2. +254 −0 src/customElements.ts
  3. +81 −0 src/util/createDomWrapper.ts
  4. +2 −0 tests/unit/all.ts
  5. +321 −0 tests/unit/customElements.ts
  6. +1 −0 tests/unit/util/all.ts
  7. +148 −0 tests/unit/util/createDomWrapper.ts
View
144 README.md
@@ -26,6 +26,11 @@ We also provide a suite of pre-built widgets to use in your applications: [(@doj
- [Widget Registry](#widget-registry)
- [Theming](#theming)
- [Internationalization](#internationalization-i18n)
- [Web Components](#web-components)
- [Attributes](#attributes)
- [Properties](#properties)
- [Events](#events)
- [Initialization](#initialization)
- [Key Principles](#key-principles)
- [Examples](#examples)
- [Example Label Widget](#example-label-widget)
@@ -565,6 +570,145 @@ const widget = createI18nWidget({
});
```
#### Web Components
Custom Widgets can be turned into [Custom Elements](https://www.w3.org/TR/2016/WD-custom-elements-20161013/) with
minimal extra effort.
Just create a `CustomElementDescriptor` factory and use the build tooling to do the rest of the work,
```ts
import { CustomElementDescriptor } from '@dojo/widget-core/customElements';
export default function createCustomElement(): CustomElementDescriptor {
return {
attributes: [
{
attributeName: 'label'
}
],
events: [
{
propertyName: 'onChange',
name: 'change'
}
]
};
};
```
##### Attributes
You can explicitly map widget properties to DOM node attributes with the `attributes` array.
```ts
{
attributes: [
{
attributeName: 'label'
},
{
attributeName: 'placeholder',
propertyName: 'placeHolder'
},
{
attributeName: 'delete-on-focus',
propertyName: 'deleteOnFocus',
value: value => Boolean(value || 0)
}
]
}
```
* `attributeName` refers to the attribute that will set on the DOM element, so, `<text-widget label="test" />`.
* `propertyName` refers to the property on the widget to set, and if not set, defaults to the `attributeName`.
* `value` lets you specify a transformation function on the attribute value. This function should return the value that
will be set on the widget's property.
Adding an attribute to the element will automatically add a corresponding property to the element as well.
```ts
// as an attribute
textWidget.setAttribute('label', 'First Name');
// as a property
textWidget.label = 'First Name';
```
##### Properties
You can map DOM element properties to widget properties,
```ts
{
properties: [
{
propertyName: 'placeholder',
widgetPropertyName: 'placeHolder'
}
]
}
// ...
textWidget.placeholder = 'Enter first name';
```
* `propertyName` is the name of the property on the DOM element
* `widgetPropertyName` is the name of the property on the widget. If unspecified, `propertyName` is used instead.
* `getValue`, if specified, will be called with the widget's property value as an argument. The returned value is returned as the DOM element property value.
* `setValue`, if specified, is called with the DOM elements property value. The returned value is used for the widget property's value.
##### Events
Some widgets have function properties, like events, that need to be exposed to your element. You can use the
`events` array to map widget properties to DOM events.
```ts
{
events: [
{
propertyName: 'onChange',
eventName: 'change'
}
]
}
```
This will add a property to `onChange` that will emit the `change` custom event. You can listen like any other
DOM event,
```ts
textWidget.addEventListener('change', function (event) {
// do something
});
```
##### Initialization
Custom logic can be performed after properties/attributes have been defined but before the projector is created. This
allows you full control over your widget, allowing you to add custom properties, event handlers, work with child nodes, etc.
The initialization function is run from the context of the HTML element.
```ts
{
initialization(properties) {
const footer = this.getElementsByTagName('footer');
if (footer) {
properties.footer = footer;
}
const header = this.getElementsByTagName('header');
if (header) {
properties.header = header;
}
}
}
```
It should be noted that children nodes are removed from the DOM when widget instantiation happens, and added as children
to the widget instance.
### Key Principles
These are some of the **important** principles to keep in mind when creating and using widgets:
Oops, something went wrong.

0 comments on commit 137d28f

Please sign in to comment.