mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] refs in recursive templates now work properly
This commit is contained in:
committed by
Samuel Degueldre
parent
74faa8bb82
commit
a9f29c4caa
@@ -299,7 +299,7 @@ interface BlockCtx {
|
|||||||
locations: IndexedLocation[];
|
locations: IndexedLocation[];
|
||||||
children: Child[];
|
children: Child[];
|
||||||
cbRefs: number[];
|
cbRefs: number[];
|
||||||
refList: (() => void)[];
|
refList: (() => void)[][];
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildContext(tree: IntermediateTree, ctx?: BlockCtx, fromIdx?: number): BlockCtx {
|
function buildContext(tree: IntermediateTree, ctx?: BlockCtx, fromIdx?: number): BlockCtx {
|
||||||
@@ -409,8 +409,7 @@ function updateCtx(ctx: BlockCtx, tree: IntermediateTree) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "ref":
|
case "ref":
|
||||||
const index = ctx.refList.push(NO_OP) - 1;
|
const index = ctx.cbRefs.push(info.idx) - 1;
|
||||||
ctx.cbRefs.push(info.idx);
|
|
||||||
ctx.locations.push({
|
ctx.locations.push({
|
||||||
idx: info.idx,
|
idx: info.idx,
|
||||||
refIdx: info.refIdx!,
|
refIdx: info.refIdx!,
|
||||||
@@ -430,10 +429,12 @@ function buildBlock(template: HTMLElement, ctx: BlockCtx): BlockType {
|
|||||||
if (ctx.cbRefs.length) {
|
if (ctx.cbRefs.length) {
|
||||||
const cbRefs = ctx.cbRefs;
|
const cbRefs = ctx.cbRefs;
|
||||||
const refList = ctx.refList;
|
const refList = ctx.refList;
|
||||||
|
let cbRefsNumber = cbRefs.length;
|
||||||
B = class extends B {
|
B = class extends B {
|
||||||
mount(parent: HTMLElement, afterNode: Node | null) {
|
mount(parent: HTMLElement, afterNode: Node | null) {
|
||||||
|
refList.push(new Array(cbRefsNumber));
|
||||||
super.mount(parent, afterNode);
|
super.mount(parent, afterNode);
|
||||||
for (let cbRef of refList) {
|
for (let cbRef of refList.pop()!) {
|
||||||
cbRef();
|
cbRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -620,8 +621,8 @@ function setText(this: Text, value: any) {
|
|||||||
characterDataSetData.call(this, toText(value));
|
characterDataSetData.call(this, toText(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeRefSetter(index: number, refs: (() => void)[]): Setter<HTMLElement> {
|
function makeRefSetter(index: number, refs: (() => void)[][]): Setter<HTMLElement> {
|
||||||
return function setRef(this: HTMLElement, fn: any) {
|
return function setRef(this: HTMLElement, fn: any) {
|
||||||
refs[index] = () => fn(this);
|
refs[refs.length - 1][index] = () => fn(this);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createBlock, mount, patch, remove } from "../../src/blockdom";
|
import { createBlock, mount, patch, remove } from "../../src/blockdom";
|
||||||
|
import { logStep } from "../helpers";
|
||||||
import { makeTestFixture } from "./helpers";
|
import { makeTestFixture } from "./helpers";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -55,3 +56,15 @@ test("is in dom when callback is called", async () => {
|
|||||||
|
|
||||||
mount(tree, fixture);
|
mount(tree, fixture);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("callback ref in callback ref with same block", async () => {
|
||||||
|
const block = createBlock('<p block-ref="0"><block-text-1/><block-child-0/></p>');
|
||||||
|
let refFn = (el: HTMLParagraphElement) => logStep(el.outerHTML);
|
||||||
|
|
||||||
|
const child = block([refFn, "child"], []);
|
||||||
|
const parent = block([refFn, "parent"], [child]);
|
||||||
|
mount(parent, fixture);
|
||||||
|
|
||||||
|
expect(fixture.innerHTML).toBe("<p>parent<p>child</p></p>");
|
||||||
|
expect(["<p>child</p>", "<p>parent<p>child</p></p>"]).toBeLogged();
|
||||||
|
});
|
||||||
|
|||||||
@@ -38,6 +38,26 @@ exports[`refs can use 2 refs with same name in a t-if/t-else situation 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`refs refs and recursive templates 1`] = `
|
||||||
|
"function anonymous(bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<p block-ref=\\"0\\"><block-text-1/><block-child-0/></p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const refs = ctx.__owl__.refs;
|
||||||
|
const ref1 = (el) => refs[\`root\`] = el;
|
||||||
|
let b2;
|
||||||
|
let txt1 = ctx['props'].tree.value;
|
||||||
|
if (ctx['props'].tree.child) {
|
||||||
|
b2 = component(\`Test\`, {tree: ctx['props'].tree.child}, key + \`__1\`, node, ctx);
|
||||||
|
}
|
||||||
|
return block1([ref1, txt1], [b2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`refs refs are properly bound in slots 1`] = `
|
exports[`refs refs are properly bound in slots 1`] = `
|
||||||
"function anonymous(bdom, helpers
|
"function anonymous(bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, mount, useRef, useState } from "../../src/index";
|
import { Component, mount, onMounted, useRef, useState } from "../../src/index";
|
||||||
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
||||||
import { xml } from "../../src/index";
|
import { xml } from "../../src/index";
|
||||||
|
|
||||||
snapshotEverything();
|
snapshotEverything();
|
||||||
@@ -100,4 +100,27 @@ describe("refs", () => {
|
|||||||
expect(console.warn).toBeCalledTimes(1);
|
expect(console.warn).toBeCalledTimes(1);
|
||||||
console.warn = consoleWarn;
|
console.warn = consoleWarn;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("refs and recursive templates", async () => {
|
||||||
|
class Test extends Component {
|
||||||
|
static components = {};
|
||||||
|
static template = xml`
|
||||||
|
<p t-ref="root">
|
||||||
|
<t t-esc="props.tree.value"/>
|
||||||
|
<t t-if="props.tree.child"><Test tree="props.tree.child"/></t>
|
||||||
|
</p>`;
|
||||||
|
root = useRef("root");
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
onMounted(() => logStep(this.root.el!.outerHTML));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Test.components = { Test };
|
||||||
|
|
||||||
|
const tree = { value: "a", child: { value: "b", child: null } };
|
||||||
|
|
||||||
|
await mount(Test, fixture, { props: { tree } });
|
||||||
|
expect(fixture.innerHTML).toBe("<p>a<p>b</p></p>");
|
||||||
|
expect(["<p>b</p>", "<p>a<p>b</p></p>"]).toBeLogged();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user