odoo17核心概念view6——用js_class扩展formview

2023-12-26 16:20

本文主要是介绍odoo17核心概念view6——用js_class扩展formview,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这是view系列的第六篇文章,我们学习用js_class来扩展view
学习odoo的一大窍门就是抄,因为odoo本身就是一个庞大的代码库,抄过来,改改就能用

1、找一个js_class的案例

搜索js_class,出现一堆结果,随便看一个

<form string="Account Entry" js_class="account_move_form">

搜索account_move_form 找到对应的js文件

/** @odoo-module **/import { registry } from "@web/core/registry";
import { createElement, append } from "@web/core/utils/xml";
import { Notebook } from "@web/core/notebook/notebook";
import { formView } from "@web/views/form/form_view";
import { FormCompiler } from "@web/views/form/form_compiler";
import { FormRenderer } from "@web/views/form/form_renderer";
import { FormController } from '@web/views/form/form_controller';
import { useService } from "@web/core/utils/hooks";export class AccountMoveController extends FormController {setup() {super.setup();this.account_move_service = useService("account_move");}async deleteRecord() {if ( !await this.account_move_service.addDeletionDialog(this, this.model.root.resId)) {return super.deleteRecord(...arguments);}}
};export class AccountMoveFormNotebook extends Notebook {async changeTabTo(page_id) {if (this.props.onBeforeTabSwitch) {await this.props.onBeforeTabSwitch(page_id);}this.state.currentPage = page_id;}
}
AccountMoveFormNotebook.template = "account.AccountMoveFormNotebook";
AccountMoveFormNotebook.props = {...Notebook.props,onBeforeTabSwitch: { type: Function, optional: true },
}
export class AccountMoveFormRenderer extends FormRenderer {async saveBeforeTabChange() {if (this.props.record.isInEdition && await this.props.record.isDirty()) {const contentEl = document.querySelector('.o_content');const scrollPos = contentEl.scrollTop;await this.props.record.save();if (scrollPos) {contentEl.scrollTop = scrollPos;}}}
}
AccountMoveFormRenderer.components = {...FormRenderer.components,AccountMoveFormNotebook: AccountMoveFormNotebook,
}
export class AccountMoveFormCompiler extends FormCompiler {compileNotebook(el, params) {const originalNoteBook = super.compileNotebook(...arguments);const noteBook = createElement("AccountMoveFormNotebook");for (const attr of originalNoteBook.attributes) {noteBook.setAttribute(attr.name, attr.value);}noteBook.setAttribute("onBeforeTabSwitch", "() => __comp__.saveBeforeTabChange()");const slots = originalNoteBook.childNodes;append(noteBook, [...slots]);return noteBook;}
}export const AccountMoveFormView = {...formView,Renderer: AccountMoveFormRenderer,Compiler: AccountMoveFormCompiler,Controller: AccountMoveController,
};registry.category("views").add("account_move_form", AccountMoveFormView);

通过上面的代码,我们看到它扩展了Renderer,Compiler,Controller三个组件,
而其他的属性通过…formView 解构赋值,值得注意的是这一句一定要放在最上面,因为后面的值会覆盖前面的,最后将这个新的结构体注册到注册表中。

2、看看formView原版

我们看看原来的formView是怎么写的,从代码看,formView是一个字典,包含了诸多属性

    type: "form",			                          视图类型		display_name: "Form",                       显示名称multiRecord: false,                            是否支持多行searchMenuTypes: [],                         搜索菜单类型,什么鬼?Controller: FormController,                 Controller组件(重要)Renderer: FormRenderer,					renderer组件(重要)ArchParser: FormArchParser,				arch解析器,(重要)Model: RelationalModel,						model (重要)Compiler: FormCompiler,					编译器(将xml文件编译成qweb模板,重要)buttonTemplate: "web.FormView.Buttons",    button模板

通常对视图的扩展就是修改它的Controller和Render组件。修改完之后生成一个新的字典,然后生成一个新的名字注册到注册表中。 然后在js_class中指定这个名称,前端解析xml的时候就会根据这个js_class名称去注册表中查找对应的信息,然后渲染页面。

/** @odoo-module **/import { registry } from "@web/core/registry";
import { RelationalModel } from "@web/model/relational_model/relational_model";
import { FormRenderer } from "./form_renderer";
import { FormArchParser } from "./form_arch_parser";
import { FormController } from "./form_controller";
import { FormCompiler } from "./form_compiler";export const formView = {type: "form",					display_name: "Form",multiRecord: false,searchMenuTypes: [],Controller: FormController,Renderer: FormRenderer,ArchParser: FormArchParser,Model: RelationalModel,Compiler: FormCompiler,buttonTemplate: "web.FormView.Buttons",props: (genericProps, view) => {const { ArchParser } = view;const { arch, relatedModels, resModel } = genericProps;const archInfo = new ArchParser().parse(arch, relatedModels, resModel);return {...genericProps,Model: view.Model,Renderer: view.Renderer,buttonTemplate: genericProps.buttonTemplate || view.buttonTemplate,Compiler: view.Compiler,archInfo,};},
};registry.category("views").add("form", formView);

3、做一个对form视图简单的扩展

js文件

/** @odoo-module **/import { registry } from "@web/core/registry";
import { formView } from "@web/views/form/form_view";
import { FormController } from '@web/views/form/form_controller';export class DemoFormController extends FormController {
};DemoFormController.template = "crax_demo.demo_form_controller"export const CraxDemoFormView = {...formView,Controller: DemoFormController,
};registry.category("views").add("crax_demo_form_view", CraxDemoFormView);

xml文件

<?xml version="1.0" encoding="UTF-8"?>
<templates><t t-name="crax_demo.demo_form_controller" t-inherit="web.FormView" t-inherit-mode="primary"><xpath expr="//div[hasclass('o_form_view_container')]" position="inside"><div style="color:red;">hello world</div></xpath></t>
</templates>

这里只是简单的在o_form_view_container里面加了一个红色的hello,world!
例子很简单,但是套路讲明白了。

这篇关于odoo17核心概念view6——用js_class扩展formview的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/540099

相关文章

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

在Node.js中使用.env文件管理环境变量的全过程

《在Node.js中使用.env文件管理环境变量的全过程》Node.js应用程序通常依赖于环境变量来管理敏感信息或配置设置,.env文件已经成为一种流行的本地管理这些变量的方法,本文将探讨.env文件... 目录引言为什么使php用 .env 文件 ?如何在 Node.js 中使用 .env 文件最佳实践引

Java Instrumentation从概念到基本用法详解

《JavaInstrumentation从概念到基本用法详解》JavaInstrumentation是java.lang.instrument包提供的API,允许开发者在类被JVM加载时对其进行修改... 目录一、什么是 Java Instrumentation主要用途二、核心概念1. Java Agent

Java抽象类Abstract Class示例代码详解

《Java抽象类AbstractClass示例代码详解》Java中的抽象类(AbstractClass)是面向对象编程中的重要概念,它通过abstract关键字声明,用于定义一组相关类的公共行为和属... 目录一、抽象类的定义1. 语法格式2. 核心特征二、抽象类的核心用途1. 定义公共接口2. 提供默认实

Python异常处理之避免try-except滥用的3个核心原则

《Python异常处理之避免try-except滥用的3个核心原则》在Python开发中,异常处理是保证程序健壮性的关键机制,本文结合真实案例与Python核心机制,提炼出避免异常滥用的三大原则,有需... 目录一、精准打击:只捕获可预见的异常类型1.1 通用异常捕获的陷阱1.2 精准捕获的实践方案1.3

使用Node.js和PostgreSQL构建数据库应用

《使用Node.js和PostgreSQL构建数据库应用》PostgreSQL是一个功能强大的开源关系型数据库,而Node.js是构建高效网络应用的理想平台,结合这两个技术,我们可以创建出色的数据驱动... 目录初始化项目与安装依赖建立数据库连接执行CRUD操作查询数据插入数据更新数据删除数据完整示例与最佳

深入浅出Java中的Happens-Before核心规则

《深入浅出Java中的Happens-Before核心规则》本文解析Java内存模型中的Happens-Before原则,解释其定义、核心规则及实际应用,帮助理解多线程可见性与有序性问题,掌握并发编程... 目录前言一、Happens-Before是什么?为什么需要它?1.1 从一个问题说起1.2 Haht

Kotlin 协程之Channel的概念和基本使用详解

《Kotlin协程之Channel的概念和基本使用详解》文章介绍协程在复杂场景中使用Channel进行数据传递与控制,涵盖创建参数、缓冲策略、操作方式及异常处理,适用于持续数据流、多协程协作等,需注... 目录前言launch / async 适合的场景Channel 的概念和基本使用概念Channel 的

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可