扩展 Laravel-admin,实现一行代码展现内联表格的功能,自动加页码,换页无刷新并保持展开状态(column-relation v2.2 发布)

column-relation v2.0 的效果图在4楼
v2.2 新增条件查询及排序(详情在12楼)
扩展 Laravel-admin 的 Column 类,实现一行代码展现内联表格的功能,自动加页码,换页保持展开状态

以下 2020.2.16 内容

目前laravel-admin v1.7.9的行展开函数expand(..)是没有页码的,想要添加页码则必须自己实现。如2.9日所述,使用回调函数的写法的确可以添加页码,可惜这个函数写起来还是挺烦的,代码很多行。而模型关联的情况非常普遍,针对每一个关联属性都要定制一个回调函数,这必定是件很烦人的事情。

用法

为解决上述问题,我写了一个函数relate(),仅需一行代码即可展现内联表格,用起来非常方便!看起来就像下面这样

$grid = new Grid(new Category());

$grid->column('name', '类别')
     ->relate('topics', ['id', 'title'=>'话题']);

这是分类控制器里的代码,内容分类与话题之间是使用函数topics()建立起一对多的关联关系的。因此,在relate()函数中,第一个参数就要写成topics。第二个参数是个数组,对应内联表格里面需要显示的字段。

上述relate()函数仅需两个参数就可以华丽的呈现内联表格(有页码、换页保持展开状态)。如果想要进一步格式化内联表格,可以象下面这样传递一个回调函数作为第三个参数(第四个参数更改每页显示个数,默认4个)。

$grid = new Grid(new Role());

$grid->column('name', '角色名称')
    ->relate('users', ['id', 'name'=> '用户'], function($user){
        $user->name=
            "<a target='_blank' href='". route('users.show', $user->id). "'>".
            "<img class='img-thumbnail' width='30px' src='".
            $user->avatar ."'> ".
            $user->name.
            "</a>";
    })
;

以上回调函数格式化name字段,将用户名转换成链接,并且添加了一个用户头像。这个回调函数的写法与需要添加页码的回调比起来,简单了很多。

需要加入内联表格的页面越多,就越有必要使用relate(..)函数,真的很方便!

安装

composer require zhaiduting/column-relation

加载

在文件 app\Admin\bootstrap.php 中添加如下代码加载扩展

use Encore\Admin\Grid\Column;
use Zhaiduting\ColumnRelation\Relate;

Column::extend('relate', Relate::class);

加载之后就可以在admin控制器里面使用relate()函数了,用法前面已经说了。

以下2020.2.9内容,不使用relate()函数的写法

经过数日摸索,终于找到了行展开后的表格添加页码的方法。效果如gif动画所示
laravel-admin内联表格【行展开】,格式化数据并添加页码!

相关代码如下,其中回调函数的写法相当繁琐

protected function grid()
{
    $grid = new Grid(new Role());

    $grid->column('id', 'ID');
    $grid->column('name', '角色名称')
        ->expand(function($model){
            $users= $model->users()
                ->paginate(2, ['*'], 'row'. $this->id)
                ->appends('page', request('page'));
            $pagination= $users->toHtml();  //或者 $users->links()

            $array= $users->map(function($user){
                $user->name=
                    "<a target='_blank' href='". route('users.show', $user->id). "'>".
                        "<img class='img-thumbnail' width='30px' src='". 
                        $user->avatar ."'> ". 
                        $user->name.
                    "</a>";
                return $user->only(['id', 'name']);
            })->toArray();
            $array[]['id']= $pagination;    //追加分页代码到新行的第一列

            return new Table(['id', '用户名'], $array);
        });

    $grid->column('permissions', '权限')->pluck('name')->label('default');
    $grid->paginate(6);

    return $grid;
}

行展开的关键代码是$grid->column(..)->expand(function($model){..}),这里面涉及到一个回调函数。分页按钮、数据格式化功能就是通过这个回调函数实现的。
1、链接http://w.bbs.cc/admin/roles?page=2&row11=2表示的是第2页、id为11的数据。
由于这是一个多栏分页的页面,分页参数彼此不能冲突,所以采用了 row1、row2、…这样的分页参数。paginate(2, ['*'], 'row'. $this->id)主要解决的就是这个参数冲突问题。
2、仅仅解决参数冲突问题还不够,还必须附带添加外层表格的分页参数,appends('page', request('page'))解决的就是参数附加问题。
3、$pagination= $users->toHtml();将前面定制好的分页代码提取出来。
4、$array[]['id']= $pagination;将提取出来的分页代码伪装成新行,添加到内联表格里面。这样页面就可以成功显示分页按钮了!
5、在expand()的回调函数内部有一个数组映射的回调函数,$users->map(function($user){..}),这个函数里面实现了格式化功能(显示用户头像并添加跳转链接)。

感觉代码写得很粗糙,尤其是$user->name的替换操作更是麻烦。如果大家有更加优雅的写法,敬请分享一下,谢谢!

这里面还有个令人不爽的大问题:点击分页按钮后,之前原本展开的行没能保持展开状态。求解!
另外,将分页代码添加到新行的话,可能需要设置colspan="2"这样的属性,也不知道怎么添加进去。
【以上2.9日提问,2.16已解】

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 3周前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 13

column-relation v1.0发布

1个月前 评论

厉害了,支持,希望我有机会用回laravel-admin,公司问题导致好久没用了

1个月前 评论

file

column-relation v1.1 发布

这个版本可以在同一个页面中加入任意多个不同的内联表格,页码互不影响,换页仍然保持展开状态。以gif图片为例,在这个用户管理页面内嵌了【他的回复、他的话题】两张子表格。如果不打算在子表格里面加入超链接,那仅仅只需两行代码即可达到目的。

$grid = new Grid(new User());
$grid->column('话题')->relate('topics', ['id', 'title'=>'标题']);
$grid->column('回复')->relate('replies', ['id', 'content'=>'内容']);

如果想做得更好一点,可以分别传入一个回调函数格式化一下(各加一个链接),代码稍微复杂了点

$grid = new Grid(new User());
$grid->column('话题')->relate('topics', ['id', 'title'=>'标题'], function($topic){
    $link= route('topics.show', $topic->id);
    $topic->title= "<a href='$link' target='_blank'>{$topic->title}</a>";
});
$grid->column('回复')->relate('replies', ['id', 'content'=>'内容'], function($reply){
    $link= route('topics.show', $reply->topic->id);
    $link= "..<a href='$link' target='_blank'> [More]</a>";
    $reply->content= Str::limit($reply->content, 160, $link);
});

这里的回调函数比较简单,但是内联表格的功能却已经是相当的华丽了。

1个月前 评论

file

column-relation v2.0 发布

这个版本的亮点是:换页无刷新(如上图所示)。不同的内嵌表格可以各换各的页,彼此互不相干,也不会因为内嵌表格换页去刷新整个页面。

下图为 v1.x 版的换页刷新效果,与 v2.0 不刷新的效果对比起来,差别还是很大的

Laravel

1个月前 评论

Call to undefined function Zhaiduting\ColumnRelation\str_replace_last()

1个月前 评论
zhaiduting (楼主) 1个月前
zhaiduting (楼主) 1个月前
zz52998 (作者) 1个月前
zz52998 (作者) 1个月前

file 一直报这个错误

3周前 评论
zhaiduting (楼主) 3周前
Arnold19910326 (作者) 3周前
zhaiduting (楼主) 3周前
Arnold19910326 (作者) 3周前

Windows服务器如果安装后没效果,请检查网站根目录下是否存在如图所示的静态资源。如果不存在,请在站点根目录下手动创建这样一个文件夹vendor\zhaiduting\column-relation,然后将 relate.js 和 relate.css 复制到这个文件夹下就可以了。 file

3周前 评论

laravel-admin 1,editable 列表内编辑数据成功,并在表单提交回调前对另一字段进行了数据修改,然后一并提交 2,点击列表中可以修改的字段,然后修改数据,修改成功, 点击修改的字段刷新成功,表单提交回调中的另一字段如何也能实时更新?

3周前 评论
zhaiduting (楼主) 3周前
Arnold19910326 (作者) 2周前

更新了包之后,折叠无法展开

file
js加载报错

环境是homestead

2周前 评论
zhaiduting (楼主) 2周前

relate($relationShip,$tableHeader,$callback, $perPage) 这里面如何加where 条件呢?比如我想查多个班级下的学生名字,filter 查处可以查到学生名字的班级,但是点击下拉展开的是班级下的所有学生,如何对学生也进行过滤,是我fiter查的学生名字?

2周前 评论
zhaiduting (楼主) 2周前
display(
    string $relationShip = '',  //模型关联函数的名称
    array $tableHeader = [] ,   //需要展示的字段列表
    callable $callback = null,  //用于格式化的回调函数
    int $perPage = 4,           //每页显示个数
    $where_or_filter = []       //条件查询,数组或回调
)

条件查询支持数组嵌套,也可以是一个回调函数(用来写一些复杂的条件或排序)

// 多条件的 $where 参数写法如下
[
    ['content', 'like', '%Necessitatibus%'], 
    ['id', '<', 300]
]

// 单一条件的写法如下
[
    'content', 'like', 'Necessitatibus%'
]
2周前 评论
zz52998 2周前
zhaiduting (作者) (楼主) 2周前

column-relation v2.2 发布

第5个参数不仅可以使用数组 $where,也可以是一个回调函数。回调里面可以任意写条件,也可以排序。

protected function grid()
{
    $grid = new Grid(new User());

    // 过滤大表格,只展示 xxx@xxx.org 的用户
    $grid->model()->where ('email', 'like', '%.org');

    // 插入内联表格,用来展示此用户的所有回复信息
    $grid->column('回复')->relate(
        'replies',                      //模型关联函数的名称
        ['id', 'content'=>'内容'],      //需要展示的字段列表
        function($reply){...},          //用于格式化的回调函数
        8,                              //每页显示个数
        function($replies, $id){
        //条件查询,也可以是回调函数(如果是数组,直接当成 ->where(..) 处理)
            $replies
                ->whereRaw( //或者使用 where([..])
                    '? < id and id < ?', [200, 250]
                )
                ->orWhere(
                //如果使用了 orWhere(),回调函数必须添加第2个参数限定结果
                    [
                        ['user_id', '=', $id],  
                        ['id', '<', 100],
                        ['id', '>', 50],
                    ]
                )
                ->orderBy('id', 'desc')
            ;
        }
    );
    ... ...

    return $grid;
}

下图是对应结果,首先筛选出 .org 的邮箱用户(大表筛选)。点击9号用户,本应该展示9号的所有回复信息,但是因为添加了条件函数,过滤了结果(内联表的数据筛选),因此下拉表格里面只显示了部分数据。
另外4个用户已经找不到符合条件的回复信息了,因此是空的(没有下拉表格了)
file

2周前 评论

请问支持异步加载数据吗?

7小时前 评论
zhaiduting (楼主) 5小时前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
未填写
文章
28
粉丝
6
喜欢
99
收藏
67
排名:141
访问:3.4 万
私信
所有博文