Skip to content

Commit f576442

Browse files
authored
Merge pull request #127 from github/fix-bind-controllers-before-custom-connectedcallback-behavior
Fix bind controllers before custom connectedcallback behavior
2 parents 456196e + a539df7 commit f576442

3 files changed

Lines changed: 88 additions & 6 deletions

File tree

src/bind.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ const controllers = new WeakSet<Element>()
66
*/
77
export function bind(controller: HTMLElement): void {
88
controllers.add(controller)
9-
if (controller.shadowRoot) {
10-
bindElements(controller.shadowRoot)
11-
listenForBind(controller.shadowRoot)
12-
}
9+
if (controller.shadowRoot) bindShadow(controller.shadowRoot)
1310
bindElements(controller)
1411
listenForBind(controller.ownerDocument)
1512
}
1613

14+
export function bindShadow(root: ShadowRoot): void {
15+
bindElements(root)
16+
listenForBind(root)
17+
}
18+
1719
const observers = new WeakMap<Node, Subscription>()
1820
/**
1921
* Set up observer that will make sure any actions that are dynamically

src/controller.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {register} from './register.js'
2-
import {bind} from './bind.js'
2+
import {bind, bindShadow} from './bind.js'
33
import {autoShadowRoot} from './auto-shadow-root.js'
44
import {defineObservedAttributes, initializeAttrs} from './attr.js'
55
import type {CustomElement} from './custom-element.js'
@@ -16,8 +16,9 @@ export function controller(classObject: CustomElement): void {
1616
this.toggleAttribute('data-catalyst', true)
1717
autoShadowRoot(this)
1818
initializeAttrs(this)
19-
if (connect) connect.call(this)
2019
bind(this)
20+
if (connect) connect.call(this)
21+
if (this.shadowRoot) bindShadow(this.shadowRoot)
2122
}
2223
defineObservedAttributes(classObject)
2324
register(classObject)

test/controller.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import {controller} from '../lib/controller.js'
2+
3+
describe('controller', () => {
4+
it('calls register', async () => {
5+
class ControllerRegisterElement extends HTMLElement {}
6+
controller(ControllerRegisterElement)
7+
const instance = document.createElement('controller-register')
8+
document.body.appendChild(instance)
9+
expect(instance).to.be.instanceof(ControllerRegisterElement)
10+
})
11+
12+
it('adds data-catalyst to elements', async () => {
13+
controller(class ControllerDataAttrElement extends HTMLElement {})
14+
const instance = document.createElement('controller-data-attr')
15+
document.body.appendChild(instance)
16+
expect(instance.hasAttribute('data-catalyst')).to.equal(true)
17+
expect(instance.getAttribute('data-catalyst')).to.equal('')
18+
})
19+
20+
it('binds controllers before custom connectedCallback behaviour', async () => {
21+
controller(class ControllerBindOrderElement extends HTMLElement {})
22+
controller(
23+
class ControllerBindOrderSubElement extends HTMLElement {
24+
connectedCallback() {
25+
this.dispatchEvent(new CustomEvent('loaded'))
26+
}
27+
}
28+
)
29+
30+
const instance = document.createElement('controller-bind-order')
31+
chai.spy.on(instance, 'foo')
32+
document.body.appendChild(instance)
33+
34+
const sub = document.createElement('controller-bind-order-sub')
35+
sub.setAttribute('data-action', 'loaded:controller-bind-order#foo')
36+
instance.appendChild(sub)
37+
38+
expect(instance.foo).to.have.been.called(1)
39+
})
40+
41+
it('binds shadowRoots after connectedCallback behaviour', async () => {
42+
controller(
43+
class ControllerBindShadowElement extends HTMLElement {
44+
connectedCallback() {
45+
this.attachShadow({mode: 'open'})
46+
const button = document.createElement('button')
47+
button.setAttribute('data-action', 'click:controller-bind-shadow#foo')
48+
this.shadowRoot.appendChild(button)
49+
}
50+
}
51+
)
52+
const instance = document.createElement('controller-bind-shadow')
53+
chai.spy.on(instance, 'foo')
54+
document.body.appendChild(instance)
55+
56+
instance.shadowRoot.querySelector('button').click()
57+
58+
expect(instance.foo).to.have.been.called(1)
59+
})
60+
61+
it('binds auto shadowRoots', async () => {
62+
controller(class ControllerBindAutoShadowElement extends HTMLElement {})
63+
const instance = document.createElement('controller-bind-auto-shadow')
64+
const template = document.createElement('template')
65+
template.setAttribute('data-shadowroot', 'open')
66+
// eslint-disable-next-line github/unescaped-html-literal
67+
template.innerHTML = '<button data-action="click:controller-bind-auto-shadow#foo"></button>'
68+
instance.appendChild(template)
69+
chai.spy.on(instance, 'foo')
70+
document.body.appendChild(instance)
71+
72+
expect(instance.shadowRoot).to.exist
73+
expect(instance).to.have.property('shadowRoot').not.equal(null)
74+
expect(instance.shadowRoot.children).to.have.lengthOf(1)
75+
instance.shadowRoot.querySelector('button').click()
76+
77+
expect(instance.foo).to.have.been.called(1)
78+
})
79+
})

0 commit comments

Comments
 (0)