手把手带你学会Odoo OWL组件开发(7):OWL项目实战使用

2023-11-10 17:59

本文主要是介绍手把手带你学会Odoo OWL组件开发(7):OWL项目实战使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本系列内容直达:】
手把手带你学习Odoo OWL组件开发(1):认识 OWL
手把手带你学会Odoo OWL组件开发(2):OWL的使用
手把手带你学会Odoo OWL组件开发(3):核心内容指南
手把手带你学会Odoo OWL组件开发(4):OWL组件
手把手带你学会Odoo OWL组件开发(5):浅析OWL原理
手把手带你学会Odoo OWL组件开发(6):API
手把手带你学会Odoo OWL组件开发(7):OWL项目实战使用


本篇内容:OWL项目实战使用

目录

    • 一、项目背景
    • 二、页面效果和预期
    • 三、实现步骤
      • 1. 创建switch的xml文件,以OWL方式编写
      • 2. 创建对应的js文件,以类组件的方式对Switch定义
      • 3. 在需要展示的页面进行引用和实例化
      • 4. 扩展basic_model.js中的search_read方法,切换Switch后调用方法:
      • 5. 引入上面的两个js文件,绑定在ListView上,并绑定在对应的Tree的js_class
      • 6. 改写menu点击事件
      • 7. 附上Switch的样式
      • 8.更新完成
    • 四、结语


一、项目背景

这次有个新需求,要求在Odoo的菜单栏上新增一个Switch的切换按钮,在进行切换后Tree视图的数据也要通过Switch值进行过滤,考虑到数据响应和后续代码的优化,在源码的基础上进行扩展的方式不太好,刚好我们前端也对OWL也有了一定的介绍,那这次我们就用OWL实战操作下吧!


二、页面效果和预期

在对Switch按钮切换时,页面数据过滤更新。
在这里插入图片描述


三、实现步骤

1. 创建switch的xml文件,以OWL方式编写

(注:此处的 owl=“1” 不可缺少):

<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve"><t t-name="owl.switchButton" owl="1"><div class="switchContainer" style="display: flex; align-items: center;"><span>存量</span><input type="checkbox" class="switch-button" id="switch-button"/><label for="switch-button" style="margin: 0 5px;"></label><span>PO存量</span></div></t></templates>

2. 创建对应的js文件,以类组件的方式对Switch定义

odoo.define('switch_owl', function (require) {"use strict";const {Component} = owl;class SwitchButton extends Component {static template="owl.switchButton";};return SwitchButton
})

3. 在需要展示的页面进行引用和实例化

既然我们是需要绑定在Tree视图上,并对数据进行过滤,那我们可以在ListController的renderButton方法中初始化,也比较利于我们绑定事件:

odoo.define('render_switch', function (require) {"use strict";var ListController = require('web.ListController');const {ComponentWrapper} = require("web.OwlCompatibility");var session = require('web.session')var framework = require("web.framework");// 引入Switch的Owl组件var switch_owl = require('switch_owl')return ListController.extend({renderButtons: function () {let self = thisthis._super.apply(this, arguments);if (this.$buttons) {//这⾥找到刚才定义的按钮和输入框this.$buttons.find('.o_list_export_xlsx').addClass('d-none');$('#switch_block').remove()// 在菜单栏目标前添加一个div来渲染Switch$('.o_menu_systray').css({'display': 'flex'}).prepend(`<div id="switch_block" style="display: flex; align-items: center"></div>`)$(document).ready(function () {// 实例化Switch + 渲染(new ComponentWrapper(self, switch_owl)).mount($('#switch_block')[0]).then(()=>{// 对Switch绑定切换事件$('#switch-button').on('click', self.proxy('switch_func'));// 从sessionStorage中获取Switch状态值用于刷新后状态勾选let switch_check = JSON.parse(window.sessionStorage.getItem('switch_check'))$('#switch-button')[0].checked = switch_check});})}},updateButtons: function () {this.$buttons.find('.o_list_export_xlsx').hide();this._super.apply(this, arguments);},// Switch勾选事件switch_func: function (ev){let self = this// 将Switch的值缓存到sessionStorage中window.sessionStorage.setItem('switch_check', $(ev.target)[0].checked)//切换后页面数据刷新self.trigger_up('reload')}});
});

4. 扩展basic_model.js中的search_read方法,切换Switch后调用方法:

odoo.define('summary_model', function (require) {"use strict";var BasicModel = require('web.BasicModel');return BasicModel.extend({_searchReadUngroupedList: function (list) {var self = this;// 从缓存中获取Switch值,并将该参数放在context中let switch_check = JSON.parse(window.sessionStorage.getItem('switch_check'))if(switch_check){list.context.information_source = 'PO通知单'}else{list.context.information_source = '存量表'}var fieldNames = list.getFieldNames();var prom;if (list.__data) {// the data have already been fetched (alonside the groups by the// call to 'web_read_group'), so we can bypass the search_readprom = Promise.resolve(list.__data);} else {prom = this._rpc({route: '/web/dataset/search_read',model: list.model,fields: fieldNames,context: _.extend({}, list.getContext(), {bin_size: true}),domain: list.domain || [],limit: list.limit,offset: list.loadMoreOffset + list.offset,orderBy: list.orderedBy,});}return prom.then(function (result) {delete list.__data;list.count = result.length;var ids = _.pluck(result.records, 'id');var data = _.map(result.records, function (record) {var dataPoint = self._makeDataPoint({context: list.context,data: record,fields: list.fields,fieldsInfo: list.fieldsInfo,modelName: list.model,parentID: list.id,viewType: list.viewType,});// add many2one recordsself._parseServerData(fieldNames, dataPoint, dataPoint.data);return dataPoint.id;});if (list.loadMoreOffset) {list.data = list.data.concat(data);list.res_ids = list.res_ids.concat(ids);} else {list.data = data;list.res_ids = ids;}self._updateParentResIDs(list);return list;});},});
});

5. 引入上面的两个js文件,绑定在ListView上,并绑定在对应的Tree的js_class

odoo.define('summary_predict_button', function (require) {"use strict";var ListView = require('web.ListView');var viewRegistry = require('web.view_registry');var dom = require('web.dom');var render_switch = require('render_switch')var ListRenderer = require('web.ListRenderer');var SumPredictModel = require('summary_model')var SumPredictRenderer = ListRenderer.extend({_renderSelector: function (tag, disableInput) {var $content = dom.renderCheckbox();if (disableInput) {$content.find("input[type='checkbox']").prop('disabled', disableInput);}return},})var BiConListView = ListView.extend({config: _.extend({}, ListView.prototype.config, {Controller: render_switch,Renderer: SumPredictRenderer,Model: SumPredictModel}),_extractParamsFromAction: function (action) {var params = this._super.apply(this, arguments);params.hasActionMenus = false;return params;},});//这⾥⽤来注册编写的视图BiConListView,第⼀个字符串是注册名到时候需要根据注册名调⽤视图viewRegistry.add('summary_predict_button', BiConListView);return BiConListView;
});

6. 改写menu点击事件

到此你可以看到Switch按钮已经渲染到页面上了,并且在切换的时候,可以将值传到search_read接口,进而对数据进行过滤,但是会出现跳转到其他模块也会出现Switch,这是我们不希望的,所以要对menu的点击事件进行改写:

odoo.define('menu_toggle', function (require) {const Menu = require("web.Menu");Menu.include({events: _.extend({'click a': '_onDropdownClicked',},Menu.prototype.events),_onDropdownClicked: function (ev) {let current_menu_xmlid = $(ev.currentTarget).attr('data-menu-xmlid')if(current_menu_xmlid == undefined) return// 需要Switch按钮的页面let menu_data_arr = ['xc_spare_parts.spare_parts_root_menu','xc_spare_parts.aggregate_forecasts_menu','xc_spare_parts.base_data_menu','xc_spare_parts.material_logic_menu','xc_spare_parts.bom_total_table_menu','xc_spare_parts.prepare_materials_menu','xc_spare_parts.week_estimates_views_menu',     			               'xc_spare_parts.alternative_prepare_materials_menu']var menu_flag = menu_data_arr.some(function (item) {return item == current_menu_xmlid})// 通过标识来对Switch进行展示和隐藏if(menu_flag){setTimeout( function() { $('#switch_block').show()}, 1000);}else{setTimeout( function() { $('#switch_block').hide()}, 1000);}},});
})

7. 附上Switch的样式

.switch-button {display: none;/*隐藏表单元素*/
}.switch-button+label {/*+选择器选择紧跟“+”左边选择器的第一个元素*/display: inline-block;position: relative;transition: all .3s;width: 60px;height: 30px;border: 1px solid #999;border-radius: 15px;background-color: #ccc;
}.switch-button:checked+label {/*选中表单后的样式,:checked表示checkbox被选中后的状态*/background-color: #169bd5;
}.switch-button+label::before {/*使用伪元素生成一个按钮*/content: '';display: block;height: 25px;width: 25px;position: absolute;border-radius: 25px;left: 2px;top: 2px;background-color: #fff;box-shadow: 0 1px 3px rgba(0, 0, 0, .4);transition: all .3s;
}.switch-button:checked+label::before {/*checkbox选中时按钮的样式*/left: 32px;transition: all .2s linear;
}

8.更新完成

将js和xml文件分别在template和__manifest__中引用,更新模块后就完成了。


四、结语

这是OWL在实际开发中的一次尝试和应用,大家有什么好的点子和建议欢迎与我们讨论哦~

这篇关于手把手带你学会Odoo OWL组件开发(7):OWL项目实战使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Spring Boot整合Redis注解实现增删改查功能(Redis注解使用)

《SpringBoot整合Redis注解实现增删改查功能(Redis注解使用)》文章介绍了如何使用SpringBoot整合Redis注解实现增删改查功能,包括配置、实体类、Repository、Se... 目录配置Redis连接定义实体类创建Repository接口增删改查操作示例插入数据查询数据删除数据更

使用python生成固定格式序号的方法详解

《使用python生成固定格式序号的方法详解》这篇文章主要为大家详细介绍了如何使用python生成固定格式序号,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录生成结果验证完整生成代码扩展说明1. 保存到文本文件2. 转换为jsON格式3. 处理特殊序号格式(如带圈数字)4

Java使用Swing生成一个最大公约数计算器

《Java使用Swing生成一个最大公约数计算器》这篇文章主要为大家详细介绍了Java使用Swing生成一个最大公约数计算器的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下... 目录第一步:利用欧几里得算法计算最大公约数欧几里得算法的证明情形 1:b=0情形 2:b>0完成相关代码第二步:加

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV