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 ...
随机推荐
- 「疫期集训day2」高地
硝烟从凡尔登高地的东方升起...我只知道这里会发生世界上前所未有的一次战役------凡尔登的法军士兵 今天运气挺好,早自习刚复习完数论和二分图,考试时又复习了状压和Tarjan 于是乎成绩惨不忍睹 ...
- TP5中的缓存使用
Thinkphp 5.0采用了 think\Cache 类来提供缓存支持 缓存支持采用驱动方式,所以缓存在使用之前,需要进行连接操作,也就是缓存初始化操作. 支持的缓存类型包括file.memcach ...
- 机器学习实战基础(二十六):sklearn中的降维算法PCA和SVD(七) 附录
- 数据可视化实例(十二): 发散型条形图 (matplotlib,pandas)
https://datawhalechina.github.io/pms50/#/chapter10/chapter10 如果您想根据单个指标查看项目的变化情况,并可视化此差异的顺序和数量,那么散型条 ...
- During handling of the above exception, another exception occurred:
今天在计算机矩阵相关性,准备删除相关性高的列中,出现了这样的问题: During handling of the above exception, another exception occurred ...
- 移除hmtl5 input type=“number”的step验证
设置 step="any"例如:<input type="number" step="any" value=""& ...
- 【RPA Starter第一课】 Uipath RPA Starter Course
今天开始学习Uipath学院上面的课程,准备考下高级开发认证. 官网全部都是英文,然后自己一步一步的翻译,解读.开始第一步. 考纲里有写这需要学习哪些课程.自己按着上面来, 第一门课: RPA Sta ...
- Java开发中的eclispe常用快捷键&全部快捷键
Java开发中的eclispe常用快捷键&全部快捷键 Ctrl+1 快速修复(经典快捷键)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ ...
- Oracle数据泵详解
一.EXPDP和IMPDP使用说明 Oracle Database 10g引入了最新的数据泵(Data Dump)技术,数据泵导出导入(EXPDP和IMPDP)的作用 1)实现逻辑备份和逻辑恢复. 2 ...
- Spring-Boot 多数据源配置+动态数据源切换+多数据源事物配置实现主从数据库存储分离
一.基础介绍 多数据源字面意思,比如说二个数据库,甚至不同类型的数据库.在用SpringBoot开发项目时,随着业务量的扩大,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源. ...