-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A new `listeners-mixin` exists which is meant to be more low-level than the `properties-mixin`. It allows us to pull out some code that’s not strictly needed for the `element-mixin`, which mostly wants to concern itself with necessities for creating custom elements. Closes #29
- Loading branch information
1 parent
c769fcf
commit cea122c
Showing
6 changed files
with
139 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* Provides declarative 'listeners' block. | ||
*/ | ||
|
||
export default superclass => | ||
class extends superclass { | ||
static get listeners() { | ||
// Mapping of event type to method name. E.g., `{ click: 'onClick' }`. | ||
return {}; | ||
} | ||
|
||
static setupListeners(target) { | ||
// Loops over mapping declared in this.listeners and calls listen. | ||
for (const [type, methodName] of Object.entries(this.listeners)) { | ||
const ok = target.listen(target.shadowRoot, type, target[methodName]); | ||
if (ok === false) { | ||
target.dispatchError( | ||
new Error( | ||
`"${type}" listener error: "${methodName}" does not exist` | ||
) | ||
); | ||
} | ||
} | ||
} | ||
|
||
static teardownListeners(target) { | ||
// Loops over mapping declared in this.listeners and calls unlisten. | ||
for (const [type, methodName] of Object.entries(this.listeners)) { | ||
const ok = target.unlisten(target.shadowRoot, type, target[methodName]); | ||
if (ok === false) { | ||
target.dispatchError( | ||
new Error( | ||
`Failed to unbind "${type}" listener: "${methodName}" does not exist` | ||
) | ||
); | ||
} | ||
} | ||
} | ||
|
||
connectedCallback() { | ||
super.connectedCallback(); | ||
this.constructor.setupListeners(this); | ||
} | ||
|
||
disconnectedCallback() { | ||
super.disconnectedCallback(); | ||
this.constructor.teardownListeners(this); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import ElementMixin from '../mixins/element-mixin.js'; | ||
import ListenersMixin from '../mixins/listeners-mixin.js'; | ||
|
||
class TestElement extends ListenersMixin(ElementMixin(HTMLElement)) { | ||
static get listeners() { | ||
return { click: 'onClick' }; | ||
} | ||
|
||
static get observedAttributes() { | ||
return ['clicks', 'count']; | ||
} | ||
|
||
static template() { | ||
return ({ clicks, count }) => ` | ||
<button id="increment" type="button">+</button> | ||
<button id="decrement" type="button">-</button> | ||
<span>clicks: ${clicks} count ${count}</span> | ||
`; | ||
} | ||
|
||
attributeChangedCallback() { | ||
this.invalidate(); | ||
} | ||
|
||
get clicks() { | ||
return Number(this.getAttribute('clicks')); | ||
} | ||
|
||
set clicks(value) { | ||
this.setAttribute('clicks', value); | ||
} | ||
|
||
get count() { | ||
return Number(this.getAttribute('count')); | ||
} | ||
|
||
set count(value) { | ||
this.setAttribute('count', value); | ||
} | ||
|
||
onClick(evt) { | ||
this.clicks++; | ||
if (evt.target.id === 'increment') { | ||
this.count++; | ||
} else if (evt.target.id === 'decrement') { | ||
this.count--; | ||
} | ||
} | ||
} | ||
|
||
customElements.define('test-element-listeners', TestElement); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { suite, it } from './runner.js'; | ||
import './fixture-element-listeners.js'; | ||
|
||
suite('x-element listeners', async ctx => { | ||
document.onerror = evt => { | ||
console.error(evt.error); | ||
}; | ||
const el = document.createElement('test-element-listeners'); | ||
ctx.body.appendChild(el); | ||
|
||
it('initialized as expected', el.clicks === 0 && el.count === 0); | ||
|
||
el.click(); | ||
it('listens on shadowRoot, not on host', el.clicks === 0 && el.count === 0); | ||
|
||
el.shadowRoot.getElementById('increment').click(); | ||
it('listens to events', el.clicks === 1 && el.count === 1); | ||
|
||
el.shadowRoot.getElementById('decrement').click(); | ||
it('works for delegated event handling', el.clicks === 2 && el.count === 0); | ||
|
||
ctx.body.removeChild(el); | ||
el.shadowRoot.getElementById('increment').click(); | ||
it('removes listeners on disconnection', el.clicks === 2 && el.count === 0); | ||
|
||
ctx.body.appendChild(el); | ||
el.shadowRoot.getElementById('increment').click(); | ||
it('adds back listeners on reconnection', el.clicks === 3 && el.count === 1); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,15 @@ | ||
/** | ||
* Base class for custom elements. | ||
* | ||
* Extends XElementBasic and XElementProperties | ||
* | ||
* Introduces template rendering using the `lit-html` library for improved | ||
* performance and added functionality. | ||
*/ | ||
|
||
import ElementMixin from './mixins/element-mixin.js'; | ||
import ListenersMixin from './mixins/listeners-mixin.js'; | ||
import LitHtmlMixin from './mixins/lit-html-mixin.js'; | ||
import PropertiesMixin from './mixins/properties-mixin.js'; | ||
import PropertyEffectsMixin from './mixins/property-effects-mixin.js'; | ||
|
||
export default LitHtmlMixin( | ||
PropertyEffectsMixin(PropertiesMixin(ElementMixin(HTMLElement))) | ||
ListenersMixin( | ||
PropertyEffectsMixin(PropertiesMixin(ElementMixin(HTMLElement))) | ||
) | ||
); |