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 ...
随机推荐
- H3c实验室-(OSPF,Nat,STP,Dhcp,Acl)v.1)
实验声明 本实验纯属学习记录性质,如有错误,请大哥帮忙提出,马上改正谢谢~还有学习H3c心态要好,他有超级多的bug!!!! 实验介绍 实验条件 实验开始 把图设计好 先说明一下RTA-RTB的线路是 ...
- CentOS7.7 安装并配置JDK 1.8
本文介绍如何在CentOS中安装oracleJDK1.8并配置环境变量 1.下载并安装jdk1.8 进入下载页:https://www.oracle.com/technetwork/java/java ...
- 钉钉内置的浏览器怎么改变title
在我项目的开发过程当中,遇到过在钉钉打开的vue写的h5页面,通过在路由切换的时候通过全局的路由钩子函数改变 document.title 的内容失效的问题. const routes = [ { p ...
- 利用docker部署elk交换机日志分析
今天我们来聊一下利用docker部署elk日志分析系统,这里解析一下elk是啥东西.elk分别是Elasticsearch,Logstash和Kibana的首字母缩写. Elasticsearch是一 ...
- 02 Vue指令
Vue指令 1.文本相关指令 <div id="app"> <!-- 插值表达式 --> <p>{{ msg }}</p> < ...
- 数据可视化基础专题(九):Matplotlib 基础(一)坐标相关
1.前言 图表要素如下图所示 # sphinx_gallery_thumbnail_number = 3 import matplotlib.pyplot as plt import numpy as ...
- 数据可视化之PowerQuery篇(一)空值(null)运算的的解决思路
https://zhuanlan.zhihu.com/p/81535007 星友们在知识星球(PowerBI星球)提出的问题中,关于空值的运算经常被提及.平时接触到的源数据常常有空值,比如Excel数 ...
- Unity - NavMeshAgent-GetStart
Select scene geometry that should affect the navigation – walkable surfaces and obstacles. Check Nav ...
- 《重学 Java 设计模式》PDF 出炉了 - 小傅哥,肝了50天写出18万字271页的实战编程资料
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! @ 目录 一.前言 二.简介 1. 谁发明了设计模式? 2. 我怎么学不会设计模式? 3. 适 ...
- 用python批量处理Excel表格,处理结果又快又好,做办公室最靓的那个仔
使用python批量处理Excel数据 让你根据Excel上所有人的身份证号码,提取出公司员工的生日 让你每个月都将公司所有人的考勤数据整理一下 类似这样的格式化的重复操作,你还在每次都使用的 ...