业务场景
我们平时在写代码或者工作中其他场景,都会按文件夹去划分不同的业务,一般的软件工具都会提供一键折叠,一键展开功能,同时odoo在字段多个分组时我们想要一键展开和折叠也需要这种功能
这里分组就类似于我们的文件夹,点击展开和折叠将文件夹中具体的内容展示出来。
演示(使用的是odoo自带的sales模块)
展开效果,点击导航栏中的展开按钮
折叠效果,点击导航栏中的折叠按钮
代码分析
前端
普及一下常见的控制器和渲染器的知识,以便更清楚的了解到我们所重载的方法
- Controller:控制器的角色是管理模型和渲染器之间的调度、在渲染器中发生动作时,它传递
该信息到控制器中并相应地执行动作。有时,它还会在模型中调用一些方法。此外,它管理
控制面板中的按钮。 - Renderer:渲染器的角色是管理视图的 DOM 元素。每个视图可以按不同的方式渲染数据。 在渲染器中,我们可以在变量 state中获取模型的状态。它调用进行渲染的 render() 方法。
odoo.define("web.web_group_expand", function (require) {
"use strict";
var qweb = require("web.core").qweb;
# 重载列表控制器的方法
require("web.ListController").include({
#start():该方法在完成微件渲染且尚未添加到 DOM 中时调用。这非常有助于渲染后任务,返回一个延迟对象。可以在 this.$el 中访问已渲染的元素。
start: function () {
# 绑定元素和事件
this.$expandGroupButtons = $(qweb.render("web_group_expand.Buttons"));
this.$expandGroupButtons
.find("#oe_group_by_expand")
.on("click", this.expandAllGroups.bind(this));
this.$expandGroupButtons
.find("#oe_group_by_collapse")
.on("click", this.collapseAllGroups.bind(this));
return this._super.apply(this, arguments);
},
# 渲染元素,分组时显示,未分组时隐藏
renderButtons: function () {
this._super.apply(this, arguments);
this.$expandGroupButtons.toggleClass("o_hidden", !this.renderer.isGrouped);
this.$buttons.append(this.$expandGroupButtons);
},
expandAllGroups: function () {
# 逐层展开,首先需要找到尚未完全展开的最高层
var layer = this.renderer.state.data;
while (layer.length) {
var closed = layer.filter(function (group) {
return !group.isOpen;
});
if (closed.length) {
# 这一层没有完全展开,扩展
this._toggleGroups(closed);
break;
}
# 这一层完全展开,移到下一层
layer = _.flatten(
layer.map(function (group) {
return group.data;
}),
true
);
}
},
collapseAllGroups: function () {
# 逐层折叠,首先需要找到尚未完全塌陷的最深层
var layer = this.renderer.state.data.filter(function (group) {
return group.isOpen;
});
while (layer.length) {
var next = _.flatten(
layer.map(function (group) {
return group.data;
}),
true
).filter(function (group) {
return group.isOpen;
});
if (!next.length) {
# 下一层完全折叠,所以折叠这一层
this._toggleGroups(layer);
break;
}
layer = next;
}
},
_toggleGroups: function (groups) {
var self = this;
var defs = groups.map(function (group) {
return self.model.toggleGroup(group.id);
});
$.when(...defs).then(
this.update.bind(this, {}, {keepSelection: true, reload: false})
);
},
});
# 重载渲染方法,更新状态,重新渲染
require("web.ListRenderer").include({
updateState: function () {
var res = this._super.apply(this, arguments);
$("nav.oe_group_by_expand_buttons").toggleClass(
"o_hidden",
!this.isGrouped
);
return res;
},
});
});
template.xml
渲染到页面的布局控件
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="web_group_expand.Buttons">
<nav class="btn-group oe_group_by_expand_buttons o_hidden">
<button
class="btn btn-secondary fa fa-expand"
id="oe_group_by_expand"
title="Expand groups"
type="button"
/>
<button
class="btn btn-secondary fa fa-compress"
id="oe_group_by_collapse"
title="Collapse groups"
type="button"
/>
</nav>
</t>
</templates>
后端
无