[FIX] compiler: t-model on select with options with dynamic values

This commit is contained in:
Lucas Perais (lpe)
2022-01-21 15:28:35 +01:00
committed by Aaron Bohy
parent 700030cc7d
commit 753d82149e
5 changed files with 353 additions and 16 deletions
+24 -4
View File
@@ -128,6 +128,7 @@ interface Context {
translate: boolean;
tKeyExpr: string | null;
nameSpace?: string;
tModelSelectedExpr?: string;
}
function createContext(parentCtx: Context, params?: Partial<Context>) {
@@ -139,6 +140,7 @@ function createContext(parentCtx: Context, params?: Partial<Context>) {
translate: parentCtx.translate,
tKeyExpr: null,
nameSpace: parentCtx.nameSpace,
tModelSelectedExpr: parentCtx.tModelSelectedExpr,
},
params
);
@@ -543,24 +545,36 @@ export class CodeGenerator {
// specific namespace uri
attrs["block-ns"] = nameSpace;
}
for (let key in ast.attrs) {
let expr, attrName;
if (key.startsWith("t-attf")) {
let expr = interpolate(ast.attrs[key]);
expr = interpolate(ast.attrs[key]);
const idx = block!.insertData(expr, "attr");
attrs["block-attribute-" + idx] = key.slice(7);
attrName = key.slice(7);
attrs["block-attribute-" + idx] = attrName;
} else if (key.startsWith("t-att")) {
let expr = compileExpr(ast.attrs[key]);
expr = compileExpr(ast.attrs[key]);
const idx = block!.insertData(expr, "attr");
if (key === "t-att") {
attrs[`block-attributes`] = String(idx);
} else {
attrs[`block-attribute-${idx}`] = key.slice(6);
attrName = key.slice(6);
attrs[`block-attribute-${idx}`] = attrName;
}
} else if (this.translatableAttributes.includes(key)) {
attrs[key] = this.translateFn(ast.attrs[key]);
} else {
expr = `"${ast.attrs[key]}"`;
attrName = key;
attrs[key] = ast.attrs[key];
}
if (attrName === "value" && ctx.tModelSelectedExpr) {
let selectedId = block!.insertData(`${ctx.tModelSelectedExpr} === ${expr}`, "attr");
attrs[`block-attribute-${selectedId}`] = "selected";
}
}
// event handlers
@@ -600,8 +614,10 @@ export class CodeGenerator {
}
// t-model
let tModelSelectedExpr;
if (ast.model) {
const {
hasDynamicChildren,
baseExpr,
expr,
eventType,
@@ -624,6 +640,9 @@ export class CodeGenerator {
"attr"
);
attrs[`block-attribute-${idx}`] = specialInitTargetAttr;
} else if (hasDynamicChildren) {
tModelSelectedExpr = `bValue${id}`;
this.addLine(`let ${tModelSelectedExpr} = ${baseExpression}[${expression}]`);
} else {
idx = block!.insertData(`${baseExpression}[${expression}]`, "attr");
attrs[`block-attribute-${idx}`] = targetAttr;
@@ -658,6 +677,7 @@ export class CodeGenerator {
isLast: ctx.isLast && i === children.length - 1,
tKeyExpr: ctx.tKeyExpr,
nameSpace,
tModelSelectedExpr,
});
this.compileAST(child, subCtx);
}
+25 -12
View File
@@ -33,6 +33,17 @@ export interface ASTComment {
value: string;
}
interface TModelInfo {
hasDynamicChildren?: boolean;
baseExpr: string;
expr: string;
targetAttr: string;
specialInitTargetAttr: string | null;
eventType: "change" | "click" | "input";
shouldTrim: boolean;
shouldNumberize: boolean;
}
export interface ASTDomNode {
type: ASTType.DomNode;
tag: string;
@@ -41,15 +52,7 @@ export interface ASTDomNode {
content: AST[];
ref: string | null;
on: { [key: string]: string };
model: {
baseExpr: string;
expr: string;
targetAttr: string;
specialInitTargetAttr: string | null;
eventType: "change" | "click" | "input";
shouldTrim: boolean;
shouldNumberize: boolean;
} | null;
model?: TModelInfo | null;
ns: string | null;
}
@@ -178,6 +181,7 @@ export type AST =
// Parser
// -----------------------------------------------------------------------------
interface ParsingContext {
tModelInfo?: TModelInfo | null;
inPreTag: boolean;
inSVG: boolean;
}
@@ -298,12 +302,10 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
const ref = node.getAttribute("t-ref");
node.removeAttribute("t-ref");
const children = parseChildren(node, ctx);
const nodeAttrsNames = node.getAttributeNames();
const attrs: ASTDomNode["attrs"] = {};
const on: ASTDomNode["on"] = {};
let model: ASTDomNode["model"] = null;
let model: TModelInfo | null = null;
for (let attr of nodeAttrsNames) {
const value = node.getAttribute(attr)!;
@@ -351,13 +353,24 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
shouldTrim: hasTrimMod && (isOtherInput || isTextarea),
shouldNumberize: hasNumberMod && (isOtherInput || isTextarea),
};
if (isSelect) {
// don't pollute the original ctx
ctx = Object.assign({}, ctx);
ctx.tModelInfo = model;
}
} else {
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
throw new Error(`Unknown QWeb directive: '${attr}'`);
}
const tModel = ctx.tModelInfo;
if (tModel && ["t-att-value", "t-attf-value"].includes(attr)) {
tModel.hasDynamicChildren = true;
}
attrs[attr] = value;
}
}
const children = parseChildren(node, ctx);
return {
type: ASTType.DomNode,
tag: tagName,