Compare commits

...

3 Commits

Author SHA1 Message Date
Géry Debongnie 0924ff63d8 wip 2022-01-13 15:22:11 +01:00
Géry Debongnie fb64355f59 wip 2022-01-13 15:18:41 +01:00
Géry Debongnie f6c9f4f2bf wip 2022-01-13 15:15:47 +01:00
6 changed files with 187 additions and 2 deletions
+2 -1
View File
@@ -20,7 +20,8 @@ function callPortal(
target: string,
content: (ctx: any, node: any, key: string) => BDom
): BDom {
return new VPortal(target, content(ctx, parent, key)) as any;
const portal = new VPortal(target, content(ctx, parent, key), ctx.__owl__) as any;
return portal;
}
function callSlot(
+1
View File
@@ -498,6 +498,7 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
beforeRemove() {}
remove() {
console.log('ddd')
elementRemove.call(this.el);
}
+2
View File
@@ -282,10 +282,12 @@ export class ComponentNode<T extends typeof Component = typeof Component>
}
beforeRemove() {
console.log('ddddddd')
this._destroy();
}
remove() {
console.log('coucou')
this.bdom!.remove();
}
+3 -1
View File
@@ -7,13 +7,15 @@ export class VPortal extends VText implements Partial<VNode<VPortal>> {
realBDom: BDom | null;
target: HTMLElement | null = null;
constructor(selector: string, realBDom: BDom) {
constructor(selector: string, realBDom: BDom, ownerComponent: ComponentNode) {
super("");
this.ownerComponent = ownerComponent;
this.selector = selector;
this.realBDom = realBDom;
}
mount(parent: HTMLElement, anchor: ChildNode) {
super.mount(parent, anchor);
this.ownerComponent.willDestroy.push(() => this.cleanup());
this.target = document.querySelector(this.selector) as any;
if (!this.target) {
let el: any = this.el;
@@ -203,6 +203,94 @@ exports[`Portal conditional use of Portal 1`] = `
}"
`;
exports[`Portal conditional use of Portal with child and div 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2;
if (ctx['state'].hasPortal) {
b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
return multi([b2]);
}
}"
`;
exports[`Portal conditional use of Portal with child and div 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { prepareList, callPortal, withKey } = helpers;
let block1 = createBlock(\`<div><span>hasPortal</span><block-child-0/></div>\`);
let block3 = createBlock(\`<p>thePortal</p>\`);
function portalContent1(ctx, node, key = \\"\\") {
return block3();
}
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block2, v_block2, l_block2, c_block2] = prepareList([1]);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`elem\`] = v_block2[i1];
let key1 = ctx['elem'];
c_block2[i1] = withKey(callPortal(ctx, node, key, '#outside', portalContent1), key1);
}
let b2 = list(c_block2, true);
return block1([], [b2]);
}
}"
`;
exports[`Portal conditional use of Portal with child and div, variation 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block2 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2;
if (ctx['state'].hasPortal) {
let b3 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
b2 = block2([], [b3]);
}
return multi([b2]);
}
}"
`;
exports[`Portal conditional use of Portal with child and div, variation 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { prepareList, callPortal, withKey } = helpers;
let block2 = createBlock(\`<span>hasPortal</span>\`, true);
let block4 = createBlock(\`<p>thePortal</p>\`, true);
function portalContent1(ctx, node, key = \\"\\") {
return block4();
}
return function template(ctx, node, key = \\"\\") {
let b2 = block2();
ctx = Object.create(ctx);
const [k_block3, v_block3, l_block3, c_block3] = prepareList([1]);
for (let i1 = 0; i1 < l_block3; i1++) {
ctx[\`elem\`] = v_block3[i1];
let key1 = ctx['elem'];
c_block3[i1] = withKey(callPortal(ctx, node, key, '#outside', portalContent1), key1);
}
let b3 = list(c_block3, true);
return multi([b2, b3], true);
}
}"
`;
exports[`Portal conditional use of Portal with div 1`] = `
"function anonymous(bdom, helpers
) {
+91
View File
@@ -638,6 +638,97 @@ describe("Portal", () => {
'<div id="outside"><p>thePortal</p></div><div><span>hasPortal</span></div>'
);
});
test("conditional use of Portal with child and div", async () => {
class Child extends Component {
static template = xml`
<div>
<span>hasPortal</span>
<t t-foreach="[1]" t-as="elem" t-key="elem">
<t t-portal="'#outside'">
<p>thePortal</p>
</t>
</t>
</div>`;
}
class Parent extends Component {
static template = xml`
<t t-if="state.hasPortal">
<Child />
</t>`;
static components = { Child };
state = useState({ hasPortal: false });
}
addOutsideDiv(fixture);
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe('<div id="outside"></div>');
parent.state.hasPortal = true;
await nextTick();
expect(fixture.innerHTML).toBe(
'<div id="outside"><p>thePortal</p></div><div><span>hasPortal</span></div>'
);
parent.state.hasPortal = false;
await nextTick();
expect(fixture.innerHTML).toBe('<div id="outside"></div>');
parent.state.hasPortal = true;
await nextTick();
expect(fixture.innerHTML).toBe(
'<div id="outside"><p>thePortal</p></div><div><span>hasPortal</span></div>'
);
});
test.only("conditional use of Portal with child and div, variation", async () => {
class Child extends Component {
static template = xml`
<span>hasPortal</span>
<t t-foreach="[1]" t-as="elem" t-key="elem">
<t t-portal="'#outside'">
<p>thePortal</p>
</t>
</t>`;
}
class Parent extends Component {
static template = xml`
<t t-if="state.hasPortal">
<div>
<Child />
</div>
</t>`;
static components = { Child };
state = useState({ hasPortal: false });
}
addOutsideDiv(fixture);
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe('<div id="outside"></div>');
parent.state.hasPortal = true;
await nextTick();
expect(fixture.innerHTML).toBe(
'<div id="outside"><p>thePortal</p></div><div><span>hasPortal</span></div>'
);
parent.state.hasPortal = false;
await nextTick();
expect(fixture.innerHTML).toBe('<div id="outside"></div>');
parent.state.hasPortal = true;
await nextTick();
expect(fixture.innerHTML).toBe(
'<div id="outside"><p>thePortal</p></div><div><span>hasPortal</span></div>'
);
});
});
describe("Portal: UI/UX", () => {