前言
- 后端有多角色时, 往往有些表格中的列需要根据条件来根据角色身份决定是不是需要该角色查看, 为此就衍生出一个需要动态控制展示某列的需求
- fastadmin框架内调用的table实际上在初始化时, 可以修改columns中的visible属性来控制是否显示, 但是这个参数只能传入bool, 不能像其它属性一样传入function来根据计算得出
- 最初的解决方案是通过后端控制器方法
$this->assignconfig(name,value)
来给JS使用, JS使用Config.name来根据结果来控制, 但是并不完美, 因为此时的通用搜索栏也需要跟着修改展示或者隐藏, 并不算统一, 也不够灵活
- 再之后想到动态的去隐藏列, 在js中监听表格的事件, 在初始化完成后, 去动态的调用table提供的接口来隐藏某列, 但是也一样, 并不完美
使用后端来动态控制输出column, 前端初始化表格时合并后端传来的数组
- 需要先将js中初始化table时的columns变量提取出来使用新的变量存储
- 在后端控制器中, 根据自己的条件, 来决定输出的column内容, 后端可直接使用二维数组即可, 因为在使用assignconfig方法后会自动给到js一个对象使用
- 前端可使用
Config.name
来接收后端使用$this->assignconfig(name,value)
方法输出的变量.
- 此时需要注意一个问题, 后端的数组编写时, 一些属性是必须使用字符串的, 但是实际上前端使用时传入的是一个function, 如果不做处理就会js报错
- 我们要做的就是遍历后端给的数组来将本应是function的变量给恢复为正确的内容, 比如其中的events,formatter,都必须是个function
- 格式处理正确后, 即可合并到原js中的columns中, 或者也可选择使用splice方法插入到指定列后也是推荐的.
- 这样处理后的效果就接近完美, 实现了将某些列在后端动态控制, 同时前端的搜索框等也就能同步的展示或者隐藏了. 跟自由, 更灵活, 对于后端开发更友好
实例代码
PHP
$addColumns = [];
if($this->auth->isSuperAdmin()){
$addColumns = [
[
"field" => 'merchant.title',
"title" => __('Merchant.title'),
"operate" => "LIKE",
"table" => "table",
"class" => "autocontent",
"visible" => true
],
[
"field" => 'merchant.avatar',
"title" => __('Merchant.avatar'),
"operate" => false,
"table" => "table",
"events" => 'Table.api.events.image',
"formatter" => 'Table.api.formatter.image',
"class" => "autocontent",
"visible" => true
],
[
"field" => 'merchant.address',
"title" => __('Merchant.address'),
"operate" => false,
"table" => "table",
"class" => "autocontent",
"visible" => true
],
];
}
$this->assignconfig('addColumns',$addColumns);
JavaScript
var table = $("#table");
var columns = [
[
{checkbox: true},
{field: 'id', title: __('Id')},
{field: 'merchant_id', title: __('Merchant_id'),visible:false,operate:false},
{field: 'goods_category_id', title: __('Goods_category_id'),visible:false,operate:false},
{field: 'title', title: __('Title'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
{field: 'category.title', title: __('Category.title'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
{field: 'link', title: __('Link'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.url},
{field: 'img', title: __('Img'), operate: false, table: table, class: 'autocontent',events: Table.api.events.image, formatter: Table.api.formatter.image},
{field: 'price', title: __('Price'), operate:'BETWEEN'},
{field: 'earn', title: __('Earn'), operate:'BETWEEN'},
{field: 'saled', title: __('Saled'), operate:false,visible:false},
{field: 'stock', title: __('Stock'),operate:false,visible:false},
{field: 'status', title: __('Status'), searchList: {"0":__('Status 0'),"1":__('Status 1')}, formatter: Table.api.formatter.toggle},
{field: 'createtime',visible:false, title: __('Createtime'), operate:false, addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
{field: 'updatetime', title: __('Updatetime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
{field: 'weigh', title: __('Weigh'), operate: false, visible:false},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
let addColumns = Config.addColumns;
addColumns.forEach(element => {
if(element.events){
let tmpEvents = eval(element.events)
element.events = tmpEvents
}
if(element.formatter){
let tmpFormatter = eval(element.formatter)
element.formatter = tmpFormatter
}
});
columns[0].splice(13,0,...addColumns);
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'weigh',
fixedColumns: true,
fixedRightNumber: 1,
columns: columns
});
Table.api.bindevent(table);