Skip to content

Commit

Permalink
feat: handle existing shadow roots when upgrading (#5679)
Browse files Browse the repository at this point in the history
* feat: handle existing shadow roots when upgrading

* Change files

Co-authored-by: EisenbergEffect <[email protected]>
  • Loading branch information
2 people authored and nicholasrice committed May 5, 2022
1 parent 55e02df commit 50d1baa
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "feat: handle existing shadow roots when upgrading",
"packageName": "@microsoft/fast-element",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ describe("The Controller", () => {

expect(element.shadowRoot?.contains(style)).to.equal(false);
});

it("should attach and detach the HTMLStyleElement supplied to .addStyles() and .removeStyles() to the shadowRoot", () => {
const { controller, element } = createController({
shadowOptions: {
Expand Down Expand Up @@ -510,5 +511,29 @@ describe("The Controller", () => {
controller.removeBehaviors([behavior], true);
expect(behavior.bound).to.equal(false);
});
})
});

context("with pre-existing shadow dom on the host", () => {
it("re-renders the view during connect", async () => {
const name = uniqueElementName();
const element = document.createElement(name);
const root = element.attachShadow({ mode: 'open' });
root.innerHTML = 'Test 1';

document.body.append(element);

new FASTElementDefinition(
class TestElement extends FASTElement {
static definition = {
name,
template: html`Test 2`
};
}
).define();

expect(root.innerHTML).to.equal("<!---->Test 2");

document.body.removeChild(element);
});
});
});
17 changes: 13 additions & 4 deletions packages/web-components/fast-element/src/components/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class Controller extends PropertyChangeNotifier {
private boundObservables: Record<string, any> | null = null;
private behaviors: Map<Behavior<HTMLElement>, number> | null = null;
private needsInitialization: boolean = true;
private hasExistingShadowRoot = false;
private _template: ElementViewTemplate | null = null;
private _styles: ElementStyles | null = null;
private _isConnected: boolean = false;
Expand Down Expand Up @@ -159,10 +160,16 @@ export class Controller extends PropertyChangeNotifier {
const shadowOptions = definition.shadowOptions;

if (shadowOptions !== void 0) {
const shadowRoot = element.attachShadow(shadowOptions);
let shadowRoot = element.shadowRoot;

if (shadowOptions.mode === "closed") {
shadowRoots.set(element, shadowRoot);
if (shadowRoot) {
this.hasExistingShadowRoot = true;
} else {
shadowRoot = element.attachShadow(shadowOptions);

if (shadowOptions.mode === "closed") {
shadowRoots.set(element, shadowRoot);
}
}
}

Expand Down Expand Up @@ -434,7 +441,9 @@ export class Controller extends PropertyChangeNotifier {
// If there's already a view, we need to unbind and remove through dispose.
this.view.dispose();
(this as Mutable<this>).view = null;
} else if (!this.needsInitialization) {
} else if (!this.needsInitialization || this.hasExistingShadowRoot) {
this.hasExistingShadowRoot = false;

// If there was previous custom rendering, we need to clear out the host.
for (let child = host.firstChild; child !== null; child = host.firstChild) {
host.removeChild(child);
Expand Down

0 comments on commit 50d1baa

Please sign in to comment.