[WICG/webcomponents] Using attributes as properties (#913)

A lot of the web components I write use a pattern to connect an attribute to a property. Just like `id` is both an attribute and a property on any HTML element, I often want this pattern for custom attributes, leading me to write:
```
customElements.define('icon-button', class extends HTMLElement {
    static get observedAttributes(){ return ['icon']; }
    constructor(){
        super();
    }
    get icon(){ return this.getAttribute('icon'); }
    set icon(value){ this.setAttribute('icon', value); }
});
```
since this is a regularly recurring pattern, it would be really nice to get this out of the box as "attribute configuration". Of course, this configuring ideally shouldn't use any new properties on this class, so here's what I propose for the above:
```
customElements.define('icon-button', class extends HTMLElement {
    static get observedAttributes(){
        return [{name: 'icon', property: true}];
    }
    constructor(){
        super();
    }
});
```
This way, we can also extend it to get some more configuration options; for example, consider a boolean attribute. Currently, we need to write:
```
    static get observedAttributes(){ return ['important']; }
    get important(){ this.hasAttribute('important'); }
    set important(value){ this.toggleAttribute('important', value); }
```
but with configurable attributes, we can simply do something like
```
    static get observedAttributes(){
        return [{name: 'important', property: true, boolean: true}];
    }
```
We could even add things like getters and setters, that can transform the attribute's value (which is always a string or `null`) into something more directly usable. For example, this
```
    get serialNumber(){ Number(this.getAttribute('serial-number')); }
    set serialNumber(value){ this.setAttribute('serial-number', '' + value); }
```
could be written as
```
    static get observedAttributes(){
        return [{
            name: 'serial-number',
            property: true,
            get: value => Number(value),
            set: value => '' + value
        }];
    }
```
The configuration options, their names and its structure are up for debate, the main point is to allow for this type of configuration using objects as elements of the array returned by `observedAttributes`, where a string would just be a shorthand for the basic, unconfigured attribute.


-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/WICG/webcomponents/issues/913

Received on Friday, 26 February 2021 21:23:19 UTC