Permalink
Browse files

feat(Component): Added Component

  • Loading branch information...
calebdwilliams committed Jul 14, 2018
1 parent ae58c00 commit 132bb34c05347a452c7daa0f9b2a0bb9db89cb67
@@ -83,6 +83,50 @@ Similar to the event bindings above, property bindings use the bracket notation
```html
<input type="text" id="username" name="username" [required]="${this.isRequired}" [value]="${this.username}">
```

## Component base

Templiteral exports a `Component` abstract class that provides a significant boilerplate for building custom elements. By utilizing the built-in static getter `boundAttributes` which returns an array of property names, you will keep your attribute and property vaules in sync.

In addition, `Component` adds a static getter for a render method (`renderer`) which will be called when any bound attribute changes. Along with the renderer, a new element method, `html` serves as an alias for `this.templiteral()`:

```javascript
import { Component } from 'templiteral';
class HelloWorld extends Component {
static get boundAttributes() {
return ['who', 'now'];
}
static get renderer() { return 'render'; }
constructor() {
super();
this.who = 'world';
}
connectedCallback() {
super.connectedCallback();
setInterval(this.updateTime.bind(this), 100);
}
updateTime() {
this.now = new Date().toLocaleString();
}
render() {
this.html`
<h1>Hello ${this.who}</h1>
<p>${this.now}</p>
`;
}
}
customElements.define('hello-world', HelloWorld);
```

The `<hello-world></hello-world>` element would now have attributes in sync with the data and would automatically re-render the time every 100 milliseconds.

## Element references

Similar to React, you can create a simple element reference inside your template with the `ref` attribute:
@@ -142,6 +142,7 @@ class Template {
this.context = context;
this.parts = [];
this.partIndicies = new Map();
this.context.$el = location;

this.eventHandlers = [];
this._init();
@@ -300,4 +301,71 @@ function templiteral(location = this, context = this) {
};
}

class Component extends HTMLElement {
static get boundAttributes() {
return [];
}

static get observedAttributes() {
return [...this.boundAttributes];
}

constructor() {
super();
const self = this;
this.constructor.boundAttributes.forEach(attr => {
Object.defineProperty(this, attr, {
get() {
return this.getAttribute(attr);
},
set(_attr) {
if (_attr) {
this.setAttribute(attr, _attr);
} else {
this.removeAttribute(attr);
}
if (this.constructor.renderer && typeof this[this.constructor.renderer] === 'function') {
this[this.constructor.renderer]();
}
}
});
});

Object.defineProperty(this, 'templiteral', {
get() {
const location = self.shadowRoot ? self.shadowRoot : self;
return templiteral(self, location);
},
enumerable: false,
configurable: false
});

Object.defineProperty(this, 'html', {
enumerable: false,
get() {
return (...args) => {
window.requestAnimationFrame(() => Reflect.apply(self.templiteral, self, args));
}
}
});
}

attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this[name] = newValue;
}
}

connectedCallback() {
if (this.constructor.renderer && typeof this[this.constructor.renderer] === 'function') {
this[this.constructor.renderer]();
}
}

disconnectedCallback() {
templateCache.delete(this);
}
}

exports.templiteral = templiteral;
exports.Component = Component;

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -138,6 +138,7 @@ class Template {
this.context = context;
this.parts = [];
this.partIndicies = new Map();
this.context.$el = location;

this.eventHandlers = [];
this._init();
@@ -296,4 +297,70 @@ function templiteral(location = this, context = this) {
};
}

export { templiteral };
class Component extends HTMLElement {
static get boundAttributes() {
return [];
}

static get observedAttributes() {
return [...this.boundAttributes];
}

constructor() {
super();
const self = this;
this.constructor.boundAttributes.forEach(attr => {
Object.defineProperty(this, attr, {
get() {
return this.getAttribute(attr);
},
set(_attr) {
if (_attr) {
this.setAttribute(attr, _attr);
} else {
this.removeAttribute(attr);
}
if (this.constructor.renderer && typeof this[this.constructor.renderer] === 'function') {
this[this.constructor.renderer]();
}
}
});
});

Object.defineProperty(this, 'templiteral', {
get() {
const location = self.shadowRoot ? self.shadowRoot : self;
return templiteral(self, location);
},
enumerable: false,
configurable: false
});

Object.defineProperty(this, 'html', {
enumerable: false,
get() {
return (...args) => {
window.requestAnimationFrame(() => Reflect.apply(self.templiteral, self, args));
}
}
});
}

attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this[name] = newValue;
}
}

connectedCallback() {
if (this.constructor.renderer && typeof this[this.constructor.renderer] === 'function') {
this[this.constructor.renderer]();
}
}

disconnectedCallback() {
templateCache.delete(this);
}
}

export { templiteral, Component };
Oops, something went wrong.

0 comments on commit 132bb34

Please sign in to comment.