[FIX] component: self mounting position keeps the reference

Have

```xml
<body t-name="webclient" />
```
and
```js

const comp = new WebClient();
comp.mount(document.body, {position: 'self'});
```

Before this commit, the body that was there before anything had happened
was *replaced* by the new body node created by the WebClient OWL component

After this commit, we ensure that the element body is the same at reference level
This commit is contained in:
Lucas Perais (lpe)
2020-03-02 17:52:22 +01:00
committed by Géry Debongnie
parent 718e5264ae
commit b4ad14edc0
2 changed files with 24 additions and 2 deletions
+6
View File
@@ -225,6 +225,12 @@ export class Fiber {
`Cannot attach '${component.constructor.name}' to target node (not same tag name)`
);
}
// In self mode, we *know* we are to take possession of the target
// Hence we manually create the corresponding VNode and copy the "key" in data
const selfVnodeData = fiber.vnode!.data ? {key: fiber.vnode!.data.key} : {};
const selfVnode = h(fiber.vnode!.sel, selfVnodeData);
selfVnode.elm = target;
target = selfVnode;
} else {
target = component.__owl__.vnode || document.createElement(fiber.vnode!.sel!);
}
+18 -2
View File
@@ -28,14 +28,30 @@ afterEach(() => {
describe("mount targets", () => {
test("can attach a component to an existing node (if same tagname)", async () => {
class App extends Component {
static template = xml`<div>app</div>`;
static template = xml`<div t-att-class="state.customClass">app<p>another tag</p></div>`;
state = useState({customClass: 'custom'});
}
const div = document.createElement("div");
div.classList.add('arbitrary');
div.innerHTML = `<p>pre-existing</p>`;
fixture.appendChild(div);
const app = new App();
await app.mount(div, { position: "self" });
expect(fixture.innerHTML).toBe("<div>app</div>");
expect(fixture.innerHTML).toBe(`<div class="arbitrary custom"><p>pre-existing</p>app<p>another tag</p></div>`);
expect(div).toBe(app.el);
app.state.customClass = 'custom2';
await nextTick();
expect(fixture.innerHTML).toBe(`<div class="arbitrary custom2"><p>pre-existing</p>app<p>another tag</p></div>`);
expect(div).toBe(app.el);
app.unmount()
// This assert is a best guess
// The use case it covers was not really thought through
// and may change in the future
expect(fixture.innerHTML).toBe("");
});
test("cannot attach a component to an existing node (if not same tagname)", async () => {