mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0924ff63d8 | |||
| fb64355f59 | |||
| f6c9f4f2bf |
@@ -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(
|
||||
|
||||
@@ -498,6 +498,7 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
|
||||
beforeRemove() {}
|
||||
|
||||
remove() {
|
||||
console.log('ddd')
|
||||
elementRemove.call(this.el);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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", () => {
|
||||
|
||||
Reference in New Issue
Block a user