[whatwg/dom] Proposal: Element.assign() (#477)

# Element.assign
*^ or something like this*

The **Element.assign()** method would assign an element with sources; Nodes, DOMStrings, or Objects of attributes and events; optionally creating a new element by tagName.

### Syntax

```js
Element.assign(elementOrTagName, ...sources);
```

---

Let me break down each part of the proposal for you to smash:

**Sub-Proposal 1**: Creating a Node when the first argument is a string:

```js
Element.assign('div');
```

**Sub-Proposal 2**: Appending nodes with the second argument onward:

```js
Element.assign(node, ...nodes);
```

**Sub-Proposal 3**: Setting attributes from properties with the second argument onward:

```js
Element.assign(node, { role: 'button' });
```

**Sub-Proposal 3.1**: Setting dashed attributes from Object values:

```js
Element.assign(node, { aria: { label: 'This text is an aria label.' } });

// otherwise:
Element.assign(node, { 'aria-label': 'This text is an aria label.' } });
```

**Sub-Proposal 4**: Adding event listeners from properties with the second argument onward:

```js
Element.assign(node, { click: (event) => { console.log(event) } });
```

---

### Examples

With an element; set a `type` of `submit` and append some child nodes:

```js
Element.assign(el, { type: 'submit' }, ...nodes);
// el.setAttribute('type', 'submit');
// el.append(...nodes);
```

With a new `<button>` element; set a `type` of `submit` and append some child nodes:

```js
Element.assign('button', { type: 'submit' }, ...nodes);
// const el = document.createElement('button');
// el.setAttribute('type', 'submit');
// el.append(...nodes);
```

With a new `<a>` element; set an `href` and append text:

```js
Element.assign('a', { href: 'https://google.com/' }, 'Google Search');
// const el = document.createElement('a');
// el.href = 'https://google.com/';
// el.append('Google Search');
```

With a new `<button>` element; append text and add a click event listener:

```js
Element.assign('button', 'Alert Something', { click: () => { alert('Something') });
// const el = document.createElement('button');
// el.append('Alert Something');
// el.addEventListener('click', () => { alert('Something') });
```

[Custom Elements / Shadow DOM example from MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements#Example):

```html
If nothing appeared below, then your browser does not support Custom Elements yet.
<x-product data-name="Ruby" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/ruby.png" data-url="http://example.com/1"></x-product>
<x-product data-name="JavaScript" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/javascript.png" data-url="http://example.com/2"></x-product>
<x-product data-name="Python" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/python.png" data-url="http://example.com/3"></x-product>
```

```js
// Create a class for the element
class XProduct extends HTMLElement {
  constructor() {
    // Always call super first in constructor
    super();

    // Create a shadow root
    const shadow = this.attachShadow({ mode: 'open' });

    shadow.append(
      // Add an img element
      Element.create('img', {
        // Set its attributes
        width: 150,
        height: 150,
        class: 'product-img',
        // Add an event listener
        onclick: () => {
          window.location = this.getAttribute('data-url');
        }
      }),
      // Add a link to the product
      Element.create('a', {
        href: this.getAttribute('data-url'),
        class: 'product-name'
      }, this.getAttribute('data-name'))
    );
  }
}

// Define the new element
customElements.define('x-product', XProduct);
```

### Rationale

I want an easier way to create elements in JavaScript. Creating just 1 functional element involves numerous methods when you factor in attributes and listeners.

This is not an original idea. Prior art includes libraries like the minimal [Bliss.js](http://blissfuljs.com/) by @LeaVerou, or Facebook’s [React](https://facebook.github.io/react/docs/react-without-jsx.html), and a handful of other popular libraries which all include very similar methods for creating new elements. This functionality has existed in other forms of older libraries as well, going back to at least jQuery’s innerHTML to Collection sugar (`$('<div></div>')`).

With sugar like `append()` and `before()`, and the like now getting into browsers, and with DOM creation still being very fashionable AFAIK (ahem, Shadow DOM, ahem), it seems DOM creation should be easier to spin up natively.

FWIW, I’m not sold on this name; `Element.assign`. I merely and shamelessly hijacked it from other prior art; `Object.assign`.

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

Received on Tuesday, 18 July 2017 02:36:53 UTC