mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] compiler: t-model on select with options with dynamic values
This commit is contained in:
committed by
Aaron Bohy
parent
700030cc7d
commit
753d82149e
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user