[FIX] components: make sure t-ref work with t-if/t-else

This commit is contained in:
Géry Debongnie
2021-12-22 08:52:51 +01:00
committed by Aaron Bohy
parent 9f2e2bcc66
commit 92cc4375f8
9 changed files with 160 additions and 33 deletions
+19
View File
@@ -141,6 +141,24 @@ function bind(ctx: any, fn: Function): Function {
return boundFn;
}
type RefMap = { [key: string]: HTMLElement | null };
type RefSetter = (el: HTMLElement | null) => void;
function multiRefSetter(refs: RefMap, name: string): RefSetter {
let count = 0;
return (el) => {
if (el) {
count++;
if (count > 1) {
throw new Error("Cannot have 2 elements with same ref name at the same time");
}
}
if (count === 0 || el) {
refs[name] = el;
}
};
}
export const UTILS = {
withDefault,
zero: Symbol("zero"),
@@ -150,6 +168,7 @@ export const UTILS = {
withKey,
prepareList,
setContextValue,
multiRefSetter,
shallowEqual,
toNumber,
validateProps,
+20 -2
View File
@@ -148,6 +148,8 @@ class CodeTarget {
hasRoot = false;
hasCache = false;
hasRef: boolean = false;
// maps ref name to [id, expr]
refInfo: { [name: string]: [string, string] } = {};
shouldProtectScope: boolean = false;
constructor(name: string) {
@@ -168,6 +170,10 @@ class CodeTarget {
result.push(`function ${this.name}(ctx, node, key = "") {`);
if (this.hasRef) {
result.push(` const refs = ctx.__owl__.refs;`);
for (let name in this.refInfo) {
const [id, expr] = this.refInfo[name];
result.push(` const ${id} = ${expr};`);
}
}
if (this.shouldProtectScope) {
result.push(` ctx = Object.create(ctx);`);
@@ -556,8 +562,20 @@ export class CodeGenerator {
const idx = block!.insertData(`(el) => refs[\`${str}\`] = el`, "ref");
attrs["block-ref"] = String(idx);
} else {
const idx = block!.insertData(`(el) => refs[\`${ast.ref}\`] = el`);
attrs["block-ref"] = String(idx);
let name = ast.ref;
if (name in this.target.refInfo) {
// ref has already been defined
this.helpers.add("multiRefSetter");
const info = this.target.refInfo[name];
const index = block!.data.push(info[0]) - 1;
attrs["block-ref"] = String(index);
info[1] = `multiRefSetter(refs, \`${name}\`)`;
} else {
let id = this.generateId("ref");
this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
const index = block!.data.push(id) - 1;
attrs["block-ref"] = String(index);
}
}
}
+2 -1
View File
@@ -12,9 +12,10 @@ import { onMounted, onPatched, onWillUnmount } from "./component/lifecycle_hooks
*/
export function useRef<T extends HTMLElement = HTMLElement>(name: string): { el: T | null } {
const node = getCurrent()!;
const refs = node.refs;
return {
get el(): T | null {
return node.refs[name] || null;
return refs[name] || null;
},
};
}