layui在odoo12上的应用,用widget覆盖原字段视图
layui是一个前端框架,提供了许多前端的组件等,layui的详情自己官网地址:https://www.layui.com/doc/去查看
下面说一下最近用layui遇到的问题和解决方式:
问题:近期做项目时候遇到一个需要将odoo的日期字段,用一个日期范围去代替。
解决方式:layui提供了日期范围选择的组件,直接去layui官网找到相关案例,然后在本地定义组件去替换日期字段,详细如下:
1、前端视图
在字段中新增widget属性,用自定义的layui组件覆盖原xml字段视图
<field name="start_end" widget="date_range_select"/>
在模板template中新增一个模板:
<t t-name="datetime_inline">
<div class="layui-inline" style="width: 100%">
<input type="text" class="layui-input" id="datetime_inline" placeholder=" - "/>
</div>
</t>
在js文件中新增date_range_select文件,内容如下:
odoo.define("date_range_select", function (require) {
"use strict";
var AbstractField = require('web.AbstractField');
var field_registry = require('web.field_registry');
var date_range_select = AbstractField.extend({
template: 'datetime_inline',
init: function () {
this._super.apply(this, arguments);
},
start: function () {
var self = this;
setTimeout(function () {
if(self.mode==='readonly'){
self.el.innerHTML="<span>" +self.value + "</span>"
}
layui.use('laydate', function () {
var laydate = layui.laydate;
laydate.render({
elem: '#datetime_inline',
range: true,
format: 'yyyy/MM/dd',
done: function (value, date, endDate) {
self._setValue(value)
}
});
console.log('查看self', self)
})
},100);
},
});
field_registry.add('date_range_select', date_range_select);
return date_range_select
});
到这里 就定义完了一个日期选择组件
注意:form、tree视图都要加上widget
2、后端模型
容易采坑:由于刚开始后端模型中定义的start_end字段为Date类型,然而我们的前端字段已经被覆盖成了日期范围,得到的值是一个字符串,而不再是原来的耽搁日期,
所以后端模型无法 直接存储我们的日期范围这个值,所以需要将原来的Date字段,更改为Char字段去存储这个值,另外再新增start_date,end_date两个字段,
存储开始结束日期,便于之后搜索视图中使用
3、搜索视图
由于我们的日期字段被修改为日期范围,搜索的时候也是搜索一个日期范围,所以在搜索视图上也要做修改,用前端js实现过滤记录。我刚开始也想过在后端做过滤,
被否决了,原因是在后端做过滤,牵扯到当前页面已经加载完成,如果要在后端做搜索过滤就会涉及到做异步加载的问题,所以就在前端直接做过滤搜索了
1、在搜索模型中新增一个搜索模型,将对应的时间范围字段自定义一个名字为:date_range_select,
<div class="col-lg-3 col-sm-6 col-12">
<span for="date_range_select" options="{'placeholder': '时间控件选择'}"/>
</div>
2、注册我们定义的控件名字,将我们的组件指向layui定好的date类型,由于别人前期已经将date类型更改为日期范围,所以此处可以跳过一步
else if (this.field.name === 'date_range_select') {
type = 'date'
}
3、新增js文件search_pannel_extend.js 内容为:
odoo.define('search_pannel_extend', function (require) {
'use strict';
var widgetRegistry = require('web.widget_registry');
var search_pannel_default = require('layui_search_panel');
var core = require('web.core');
var proposition = require('layui_search_proposition');
var layui_search_proposition = proposition.layui_search_proposition;
var pyeval = require('web.py_utils');
var Widget = require('web.Widget');
var framework = require('web.framework');
var crash_manager = require('web.crash_manager');
var session = require('web.session');
search_pannel_default.include({
events: _.extend({}, search_pannel_default.prototype.events, {
'click .add_new': '_AddRecord',
'click .export': '_Export',
'click .import': '_Import'
}),
/**
* 新增记录
* @private
*/
_AddRecord: function (event) {
var self = this;
event.stopPropagation();
this.do_action({
name: '新增',
type: 'ir.actions.act_window',
view_type: 'form',
view_mode: 'form',
res_model: this.getParent().model_name,
views: [[false, 'form']],
flags: {mode: 'edit'},
target: 'new',
context: {'dialog_size': $(event.currentTarget).attr("dialog_size") || 'large'}
}, {
on_close: function () {
self.trigger_up('reload');
}
})
},
/**
* 导出
* @private
*/
_Export: function (event) {
var self = this;
var ids = self.get_records();
if (ids.length > 0) {
this.do_action({
'name': '导出',
'type': 'ir.actions.act_url',
'url': $(event.currentTarget).attr("url") + '?ids=' + JSON.stringify(ids),
'target': 'new',
'tfs_close': true
})
} else {
layer.msg('请勾选需要导出的行!', {icon: 2});
}
},
get_records: function () {
// 获取勾选项
var self = this;
var records = [];
var records_list = self.getParent().getParent().getSelectedRecords().map(function (record) {
records.push(record.res_id)
});
return records
},
/**
* 导入
* @private
*/
_Import: function (event) {
var self = this;
this.do_action({
name: '导入',
type: 'ir.actions.client',
tag: 'file_import',
context: {'dialog_size': 'medium', 'url': $(event.currentTarget).attr("url")},
target: 'new'
}, {
on_close: function () {
self.trigger_up('reload');
}
})
}
});
// 日期范围选择控件扩展
var date_range_select_search_pannel = search_pannel_default.extend({ events: _.extend({}, search_pannel_default.prototype.events, {
'click .report_repair': "_DateRange"
}), // 日期范围
_DateRange: function () {
var self = this;
this._rpc({
model: 'ir.model.data',
method: 'xmlid_to_res_id',
args: ['repairManageForXian.outsource_manage_project_form']
}).then(function (view_form_id) {
self.do_action({
name: '日期范围',
type: 'ir.actions.act_window',
view_type: 'form',
view_mode: 'form',
res_model: 'repair_manage.outsource_manage_project',
views: [[view_form_id, 'form']],
target: 'new'
}, {
on_close: function () {
self.trigger_up('reload');
}
})
})
}, // 读取模板,同时读取属性并构造搜索对象
renderElement: function () {
var $el;
var bHaveExt = false;
this.propositions = [];
$el = $(core.qweb.render(this.pannel_template, {widget: this}).trim());
var fields_place_holders = $el.find("[for]");
for (var i = 0; i < fields_place_holders.length; i++) {
var holder = fields_place_holders[i];
var filed_name = $(holder).attr('for');
var options = $(holder).attr('options') || "{'range': true}"; //因xml模板传过来为string类型,故此不能用Obj
options = pyeval.py_eval(options);
options.funcs = {};
var field = this.fields[filed_name];
// 如果有字段或者为聚合搜索输入框则渲染
if (field || filed_name === 'date_range_select') {
// 因原有field会被frozen冻结,所以需要复制一份调用
var copy_field = Object.assign({}, field);
// odoo12这里field没有name属性
copy_field.name = filed_name;
var prop = new layui_search_proposition(this, copy_field, options);
prop.replace(holder);
this.propositions.push(prop);
bHaveExt = true
}
}
this._replaceElement($el);
}, commit_search: function () {
var domains = [];
_.each(this.propositions, function (proposition) {
var domain = proposition.get_domain();
console.log(domain)
if (!domain) {
return
} else if (domain.length == 2){
domains.push([
['start_date', '<=', domain[1][2]],
['end_date', '>=', domain[0][2]]
])
} else {
domains.push(domain)
} });
this.trigger_up('search', {
domains: domains
});
} });
widgetRegistry.add('date_range_select_search_pannel', date_range_select_search_pannel);
return {
date_range_select_search_pannel: date_range_select_search_pannel
}
到这里 就全部结束了
layui在odoo12上的应用,用widget覆盖原字段视图的更多相关文章
- .net mvc + layui做图片上传(二)—— 使用流上传和下载图片
摘要:上篇文章写到一种上传图片的方法,其中提到那种方法的局限性,就是上传的文件只能保存在本项目目录下,在其他目录中访问不到该文件.这与浏览器的安全性机制有关,浏览器不允许用户用任意的路径访问服务器上的 ...
- .net mvc + layui做图片上传(一)
图片上传和展示是互联网应用中比较常见的一个功能,最近做的一个门户网站项目就有多个需要上传图片的功能模块.关于这部分内容,本来功能不复杂,但后面做起来却还是出现了一些波折.因为缺乏经验,对几种图片上传的 ...
- layui结合SpringMVC上传文件以及携带额外的参数上传文件
今天在使用layui的过程中,遇到了使用其上传文件的模块.自己感觉文件上传还是bootstrapfileinput插件比较好用一些,灵活方便,bootstrapfileinput使用方法参考:http ...
- .Net之Layui多图片上传
前言: 多图上传在一些特殊的需求中我们经常会遇到,其实多图上传的原理大家都有各自的见解.对于Layui多图上传和我之前所说的通过js获取文本框中的文件数组遍历提交的原理一样,只不过是Layui中的up ...
- 在选定的数据源上未找到名为“TitleSub”的字段或属
在.NET开发过程中时常会遇到“在选定的数据源上未找到名为“TitleSub”的字段或属性”的错误”,导致这类错误的原因有很多,在我的项目中,详细情况是这样:1.有两个控件:DropDownList类 ...
- layui + jfinal 实现上传下载
1.需要把jfinal的环境配置好 2.导入相关的库文件 layui的库文件 就是这两个文件需要导入到自己的页面 注意:jfinal总会把路径拦截,所以需要静态文件处理.本人不太懂.就网上找了下,说w ...
- Struts2配合layui多文件上传--下载
先说上传: 前台上传文件的js代码: var demoListView = $('#demoList') ,uploadListIns = upload.render({ elem: '#testLi ...
- php+layui实现图片上传与预览
端代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <titl ...
- Layui多文件上传进度条
Layui原生upload模块不支持文件上传进度条显示,百度,谷歌找了一下不太适用.后面找到一个别人修改好的JS,替换上去,修改一下页面显示即可使用,一下是部分代码 HTML: <div cla ...
随机推荐
- BZOJ 1131 [POI2008] STA-Station 题解
题目 The first stage of train system reform (that has been described in the problem Railways of the th ...
- 深度学习论文翻译解析(九):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
论文标题:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition 标题翻译:用于视觉识别的深度卷积神 ...
- 1. 初识Jackson -- 世界上最好的JSON库
要想人前显贵,必须背后受罪.关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis.中 ...
- Django---进阶2
目录 数据的查,改,删 django orm中如何创建表关系 django请求生命周期流程图(必会) 路由层 路由匹配 无名分组 有名分组 无名有名是否可以混合使用 反向解析 作业 数据的查,改,删 ...
- CBV源码与APIView源码解析
一.CBV源码解析 在我们写cbv的时候在url中和fbv的区别就是是否调用了as_view()方法,所以关键入手点就是这个方法 @classonlymethod # 这是类的绑定方法,这个cls是我 ...
- python 魔法方法总结
目录 一.__str__ 二.__repr__ 三.__format__ 四.__del__ 五.__dict__和__slots__ 六.__item__.__attr__系列 七.__init__ ...
- JVM 学习笔记(三)
一:使用jvisualvm工具查看堆内存 visualgc插件下载链接 : https://visualvm.github.io/pluginscenters.html --->选择对应版本链接 ...
- Scala 基础(七):Scala 运算符
1 算术运算符 算术运算符(arithmetic)是对数值类型的变量进行运算的,在Scala程序中使用的非常多. 细节说明: 1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留 ...
- Linux06 /Python web项目部署
Linux06 /Python web项目部署 目录 Linux06 /Python web项目部署 1. 部署方式 2. 纯后端代码部署/CRM为例 1. 部署方式 2. crm项目详细部署步骤 3 ...
- 用Graphviz画简单依赖图示例
代码: digraph module { 0 [label="global.h"]; 1 [label="bst_operator.c"]; 2 [label= ...