Laravel Yajra 数据表呈现自定义 html / 列样式

Posted

技术标签:

【中文标题】Laravel Yajra 数据表呈现自定义 html / 列样式【英文标题】:Laravel Yajra datatables rendering custom html / column styling 【发布时间】:2017-07-09 07:56:44 【问题描述】:

我花了几天的时间研究数据表和 yajra 包,也就是说,我离得到我需要的结果还差得很远,如果有人比我的新手方法有更多的知识,我将不胜感激!

为了帮助更好地解释,我附上了两张图片,第一张图片是一个已经实现了这个的应用程序,第二张是我抛出的一个快速模拟以显示差异。


我希望达到的理想结果...


我目前的看法...


我基本上是在尝试将自定义 html 添加到需要该功能的每个列中。通过返回一个自定义数组,我设法取得了一些成功:

foreach ($tasks as $task) 
    $checkBox = '<div class="checkbox"><input type="checkbox" value="63"><label></label></div>';
    $taskPriority = '<span class="text-info inline-block">Medium</span>';
            ... so on ...
    $row = array(
        $checkBox,
        $taskPriority,
        ... so on ...
    );
    $rows[] = $row;

$list['data'] = $rows;
return $list;

虽然这行得通,但我不会说它是最好的方法,并且可以想象有什么更好、更优雅的方法来做到这一点?

我知道 yajra 有 addColumn 和 editColumn 方法,我已经使用它们来添加一个操作列,因为这是唯一一个似乎可以呈现任何 html 的方法,除了 addColumn('action', 'blah blah' 之外的任何其他方法) 似乎不想呈现 html,而是将其显示为行中的原始文本。

以防万一这是为了帮助任何人,这是为获取表数据而进行的 Ajax 调用。

$('#taskstable').DataTable(
    "processing": true,
    "retrieve": true,
    "serverSide": true,
    'paginate': true,
    'searchDelay': 700,
    "bDeferRender": true,
    "responsive": true,
    "autoWidth": false,
    "pageLength": 5,
    "lengthMenu": [[5, 10, 25, 50, 100], [5, 10, 25, 50, 100]],
    ajax: '/tasks/get-tasks'
);

希望有人可以帮助减轻新手的压力!谢谢。

【问题讨论】:

【参考方案1】:

兄弟我能告诉你一些想法,这可能会帮助你得到你想要的结果。 控制器:

public function index(Request $request)
    
        $data = [];
        $data['page_title'] = trans($this->trans_path . 'general.page.index.page-title');
        $data['show_modal'] = false;
        $data['trans_path'] = $this->trans_path;
        if ($request->get('add') && $request->get('add') == "true") 
            $data['show_modal'] = true;
        

        // TODO: Confirm this logic
        //count no. of promoter admin
        $data['promoter'] = User::where('user_type', AclHelper::getUsersTypeKey('promoter-admin'))->count();

        // for mapping policy
        $data['admin_user_model'] = new AdminUser();

        //generate add Button
        $data['add_btn_html'] = view($this->loadDefaultVars($this->view_path . '.partials._promoter_add_button'))->render();
        $data['assignable_user_roles'] = $this->getAssignableRolesByAuthUser();

        return view($this->loadDefaultVars($this->view_path . '.index'), compact('data'));
    

    public function search(Request $request)
    

        $data = [];
        $columns = ['rud.*', 'us.first_name as promoter_first_name', 'us.last_name as promoter_last_name', 'users.email', 'users.username',
            'r.name', 'r.display_name', 'rud.created_by', 'rud.promoter_id', 'users.enabled'];
        $users = $this->getUserListJoinQuery($columns)
            ->leftJoin('role_users_details as us', 'rud.promoter_id', '=', 'us.id')
            ->groupBy('users.id');

        if (in_array(AclHelper::getUsersTypeKey('super-admin'), AclHelper::getUserRoles(), 1) ||
            in_array(AclHelper::getUsersTypeKey('support-admin'), AclHelper::getUserRoles(), 1)
        ) 
            $users->where('users.id', '!=', auth()->user()->id);
            $data['users'] = $users->get();
         else 

            if (in_array(AclHelper::getUsersTypeKey('promoter-admin'), AclHelper::getUserRoles(), 1))
                $data['users'] = $users->where('rud.promoter_id', Auth::user()->id)->get();
            elseif (in_array(AclHelper::getUsersTypeKey('promoter-editor'), AclHelper::getUserRoles(), 1)) 
                $promoter_id = Auth::user()->userDetail->promoter_id;
                $users->where('r.name', '!=', AclHelper::getUsersTypeKey('promoter-editor'));
                $data['users'] = $users->where('rud.promoter_id', $promoter_id)->get();
             else 
                return response('Unauthorized request made.', 401);
            
        

        return Datatables::of($data['users'])
            ->editColumn('user_id', function ($users) 
                $data = view($this->loadDefaultVars($this->view_path . '.partials._action_fields'), compact('users'))->render();
                return $data;
            )
            ->editColumn('profile_image', function ($users) 
                if (!isset($users->profile_image)) 
                    return "";
                
                return '<img src="' . asset(config('neptrox.admin_user_path.thumbnail') . $users->profile_image) .
                '"  style="height: 40px;" >';
            )
            ->editColumn('name', function ($users) 
                return $users->first_name . ' ' . $users->middle_name . ' ' . $users->last_name;
            )
            ->editColumn('gender', function ($users) 
                if ($users->gender === 'male')
                    return 'Male';
                elseif ($users->gender === 'female')
                    return 'Female';
                else
                    return 'Other';
            )
            ->editColumn('user_type', function ($users) 
//                return $users->pivot->display_name;
                return config('neptrox.admin-users-roles.' . $users->name . '.title');
            )
            ->editColumn('promoter', function ($users) 
                return $users->promoter_first_name . ' ' . $users->promoter_last_name;
            )
            ->editColumn('status', function ($users) 
                if ($users->enabled === 1) 
                    return "<span class='text-success'> " .
                    '<i class="fa fa-check-circle-o text-info"></i>' .
                    "</span>";
                
                return "<span class='text-danger'>" .
                '<i class="fa fa-ban text-danger"></i>' .
                "</span>";
            )
            ->make(true);

    

jquery 脚本

<script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js" type="text/javascript"></script>
<script>

    (function (options) 

        var route_url = options.dataTableConfigVariable.route_url;
        var columns = options.dataTableConfigVariable.columns;
        var order = options.dataTableConfigVariable.orderColumn;
        if (order == 'undefined' || order == null || order == "") 
            order = 1;
        
        var config = 
            "dom": '<t>' +
            '<"card-footer card-pagination"<"row"<"col-md-8"p><"col-md-4 form-design1 right"l>>>',
            "oLanguage": 
                "sLengthMenu": " _MENU_ ",
                "sSearchPlaceholder": "Search",
                "oPaginate": 
                    "sNext": "<span aria-hidden='true'>»</span><span class='sr-only'>Next</span>",
                    "sPrevious": "<span aria-hidden='true'>«</span><span class='sr-only'>Previous</span>"
                ,
            ,
            processing: true,
            serverSide: true,
            ajax: 
                type: 'POST',
                url: route_url.dataTable_url,
                data: 
                    _token: $('meta[name=csrf-token]').attr("content")
                
            ,
            columns: columns,
            'order': [[order, 'asc']]
        ;

        //initialize dataTables
        var table = $('table.table').DataTable(config);

        $('#searchField').keyup(function()
            table.search($(this).val()).draw() ;
        );


        //Enables or disables the performer and reload the ajax after success
        $('body').on('click', '.enableDisable', function (e) 
            e.preventDefault();
            var url = $(this).attr('href');
            $.ajax(
                type: 'GET',
                url: url,
                success: function (response) 
                    table.ajax.reload(null, false);
                
            );
        );

        //toggle all checkbox checked or unchecked
        $('body').on('click', 'input[name="checkAll"]', function () 
            var checkBoxes = $("input[name=checkbox\\[\\]]");
            checkBoxes.prop("checked", $(this).prop("checked"));
        );

        //enable selected performers
        $('body').on('click', '#enable', function (e) 
            var url = route_url.enableAll;
            enableDisablePerformer(e, url);
        );

        //disable selected performers
        $('body').on('click', '#disable', function (e) 
            var url = route_url.disableAll;
            enableDisablePerformer(e, url);
        );

        function enableDisablePerformer(e, url) 
            e.preventDefault();
            var formData = $('input[name^=checkbox]');
            var data = ;
            formData.each(function (index) 
                if ($(this).is(':checked')) 
                    data[index] = $(this).val();
                
            );
            $.ajax(
                type: 'POST',
                url: url,
                data: 
                    _token: $('meta[name=csrf-token]').attr("content"),
                    id: data
                ,
                success: function (response) 
                    if (response == 'ok') 
                        table.ajax.reload(null, false);
                        $('body').find('input[name="checkAll"]').prop('checked', false);
                    
                
            );
        


        //Delete confirmation popup
        $('body').on('click', '.try-sweet-warningConfirm', function () 
            var id = $(this).attr('id');
            swal(
                title: " trans($trans_path.'general.delete.sure') ",
                text: " trans($trans_path.'general.delete.message') ",
                type: "warning",
                showCancelButton: true,
                confirmButtonColor: " trans($trans_path.'general.delete.confirmButtonColor') ",
                confirmButtonText: " trans('general.button.delete') ",
                cancelButtonText: " trans('general.button.cancel') ",
                closeOnConfirm: true
            , function (isConfirm) 
                if (isConfirm) 
                    $.ajax(
                        type: 'POST',
                        url: route_url.delete,
                        data: 
                            _token: $('meta[name=csrf-token]').attr("content"),
                            id: id
                        ,
                        success: function (response) 
                            table.row($(this).closest('tr')).remove().draw();
                            if (response == 'ok') 
                                swal(
                                    title: " trans($trans_path.'general.status.delete') ",
                                    text: " trans($trans_path.'general.status.deleted') ",
                                    type: "success",
                                    timer: 2000,
                                    confirmButtonColor: " trans($trans_path.'general.delete.confirmButtonColor') "
                                );
                            
                        
                    );

                
            );
        );

        //Delete bulk confirmation popup
        $('body').on('click', '#delete', function () 
            swal(
                title: " trans($trans_path.'general.delete.sure') ",
                text: " trans($trans_path.'general.delete.message') ",
                type: "warning",
                showCancelButton: true,
                confirmButtonColor: " trans($trans_path.'general.delete.confirmButtonColor') ",
                confirmButtonText: " trans('general.button.delete') ",
                cancelButtonText: " trans('general.button.cancel') ",
                closeOnConfirm: true
            , function (isConfirm) 
                if (isConfirm) 
                    var url =route_url.delete;
                    deleteBulkPerformer(url);
                    $('body').find('input[name="checkAll"]').prop('checked', false);
                    swal(
                        title: " trans($trans_path.'general.status.delete') ",
                        text: " trans($trans_path.'general.status.deleted') ",
                        type: "success",
                        timer: 2000,
                        confirmButtonColor: " trans($trans_path.'general.delete.confirmButtonColor') "
                    );
                
            );
        );

        function deleteBulkPerformer(url)
            var formData = $('input[name^=checkbox]');

            var data = ;
            formData.each(function (index) 
                if ($(this).is(':checked')) 
                    data[index] = $(this).val();
                
            );
            $.ajax(
                type: 'POST',
                url: url,
                data: 
                    _token: $('meta[name=csrf-token]').attr("content"),
                    id: data,
                    bulk: 'bulk'
                ,
                success: function (response) 
                    if (response == 'ok') 
                        table.row($(this).closest('tr')).remove().draw();
                    
                
            );
        

    )(dataTableConfigVariable:dataTableConfigVariable);

</script>

查看页面

 <script>
        var dataTableConfigVariable = 
            route_url: 
                dataTable_url:  'route("admin.admin_users.search")',
                enableAll: 'route("admin.admin_users.enableAll")',
                disableAll: 'route("admin.admin_users.disableAll")',
                delete: 'route("admin.admin_users.delete")'
            ,
            columns: [
                data: 'user_id', name: 'user_id', orderable: false, searchable: false,
                data: 'profile_image', name: 'profile_image', orderable: false, searchable: false,
                data: 'name', name: 'name',
                data: 'user_code', name: 'user_code', orderable: false,
                data: 'email', name: 'email',
                data: 'username', name: 'username',
                data: 'gender', name: 'gender',
                data: 'user_type', name: 'user_type',
                data: 'promoter', name: 'promoter', orderable: false, searchable: false,
                data: 'status', name: 'status', orderable: false, searchable: false,
            ],
            orderColumn: 2
        ;
    </script>

【讨论】:

感谢您抽出宝贵的时间发布您的代码,我会尽快在移动设备上查看它,因此我无法看到整个帖子,但期待阅读您的解决方案:) 谢谢【参考方案2】:

截至我发布此答案时,我发现的最简单的方法如下,话虽如此,我确信这不是最好的方法,也许及时找到比我更有经验的人能够发布更好的解决方案。


在我的项目中,我使用了一个名为 Laravel Collective 的特定包,可以找到:...here..

使用这个包可以让你访问一个辅助类和外观。通过针对我的应用程序的一些细微修改,我能够充分利用这个包。

一种类似的方法是这样做:

public function getTasks()

    $tasks = $this->taskInterface->model()->all();
    return $this->datatables->collection($tasks)
        ->editColumn('name', function ($model) 
            return HtmlFacade::link("admin/tasks/$model->id", $model->name);
        )
        ->addColumn('action', function($query) 
            return view('backend.global.tables.actions.all-tasks-actions', compact('query'));
        )
        ->make(true);

注意

使用时返回 HtmlFacade::link();方法这将返回在数据表上呈现的 html,可以通过查看文档找到完整的方法列表,或者在我的情况下,通过其自身的类并查看源代码让我更好地理解了他们的包工作,不仅如此,它还提供了向类添加更多方法的能力,这就是我获得所需结果的方式。

我不打算发布所有自定义类,因为我认为它与我添加的方法或与开箱即用的包非常相似的方法对将来帮助任何人没有太大关系,唯一的区别是允许 onclick JavaScript 事件和倾斜 CSS。

这个答案的寓意是让与我处于类似位置的其他人知道,如果您已经在使用这个包,那么您可能不需要手动将所有行转换为数组,只是为了将自定义 html 传递给视图我不再需要这样做:

 $rows = [];
 $checkBox = '<div class="checkbox"><input type="checkbox" value="63"><label></label></div>';
 $taskPriority = '<span class="text-info inline-block">Medium</span>';
 ect... As seen in original post..

相反,您可以传递自定义属性、类并从 laravel 集合包中构建,这是 laravel 集合附带的链接方法,可以作为向其包中添加自定义方法的构建块。

public function link($url, $title = null, $attributes = [], $secure = null, $escape = true)

    $url = $this->url->to($url, [], $secure);

    if (is_null($title) || $title === false) 
        $title = $url;
    

    if ($escape) 
        $title = $this->entities($title);
    

    return $this->toHtmlString('<a href="' . $url . '"' . $this->attributes($attributes) . '>' . $title . '</a>');

这应该让人们了解如何轻松修改此 Html 生成器以满足您的要求,正如我所说,我确信这不是实现相同(如果不是更好)结果的最佳和最优雅的愿望,所以我将离开对未来解决方案开放的问题我只是想我会分享我的解决方案。

【讨论】:

【参考方案3】:

您可以在下面的代码中找到答案。我已经共享了主索引函数和视图文件。

控制器代码:

 public function index(Request $request)

    if ($request->ajax()) 
        $data = DB::table('issue_details as id')
            ->join('collection_batch as cb','cb.issue_no','=','id.issue_no')
            ->join('customers as c','c.id','=','cb.customer_id')
            ->groupBy(['id.issue_no','c.name','cb.collection_amount','cb.balance_amount','cb.discount_amount'])
            ->get(['id.issue_no','c.name as customer_name','cb.collection_amount as paid_amount','cb.balance_amount as due_amount',
                'cb.discount_amount',
                DB::raw('sum(id.order_quantity-id.returned_quantity) as total_order_quantity'),
                DB::raw('sum(id.total_price) as total_order_price')]);

        return Datatables::of($data)
            ->addIndexColumn()
            ->addColumn('action', function($row)
                $buttons='';
                $buttons .= '<a href="'.route('collections.show', $row->issue_no).'"> <button class="btn btn-warning btn-xs">Show</button> </a>';
                $buttons .= '<button '.($row->due_amount==0 ? 'disabled style="display:none"' : "").' class="btn btn-info btn-xs" id="'.$row->issue_no.'" onclick="collectionEdit(this.id)">Edit </button>';
                return $buttons;
            )
            ->rawColumns(['action'])
            ->make(true);
    
    return view('collection.index');

查看文件代码:

<div class="content-wrapper">
<div class="content-header">
    <div class="container-fluid">
        <div class="row mb-2">
            <div class="col-sm-6">
                <h1 class="m-0">Collection History</h1>
            </div>
            <div class="col-sm-6">
                <ol class="breadcrumb float-sm-right">
                    <li class="breadcrumb-item"><a href=" route('home') ">Home</a></li>
                    <li class="breadcrumb-item"><a href=" route('collections') ">Collection History</a></li>
                </ol>
            </div>
        </div>
    </div>
</div>

<section class="content">
    <div class="container-fluid">
        <div class="row">
            <div class="col-12">
                <div class="card">
                    <div class="card-header">
                    </div>
                    <div class="card-body">
                        <table id="datatable" class="table table-bordered table-striped">
                            <thead>
                            <tr>
                                <th>Sl No</th>
                                <th>Invoice No</th>
                                <th>Customer</th>
                                <th>Total Price</th>
                                <th>Paid</th>
                                <th>Due</th>
                                <th>Discount</th>
                                <th>Action</th>
                            </tr>
                            </thead>
                            <tbody>

                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</section>

**JS Part:**
<script type="text/javascript">
        $(function() 
            var i = 1;
            var table = $('#datatable').DataTable(
                processing: true,
                serverSide: true,
                ajax: " route('collections') ",
                columns: [
                    "render": function() 
                        return i++;
                    
                ,
                    
                        data: 'issue_no',
                        name: 'issue_no'
                    ,
                    
                        data: 'customer_name',
                        name: 'customer_name'
                    ,
                    
                        data: 'total_order_price',
                        name: 'total_order_price'
                    ,
                    
                        data: 'paid_amount',
                        name: 'paid_amount'
                    ,
                    
                        data: 'due_amount',
                        name: 'due_amount'
                    ,
                    
                        data: 'discount_amount',
                        name: 'discount_amount'
                    ,
                    
                        data: 'action',
                        name: 'action',
                        orderable: false,
                        searchable: false
                    
                ],
                createdRow: function ( row, data, index ) 
                    if (data['due_amount'] > 0) 
                        $('td', row).eq(4).css('background-color', '#f4511e','color','#ffffff');
                        $('td', row).eq(4).css('color','#ffffff');
                     else 
                    
                    $('td', row).eq(3).addClass('text-right');
                    $('td', row).eq(4).addClass('text-right');
                    $('td', row).eq(5).addClass('text-right');
                    $('td', row).eq(6).addClass('text-right');
                
            );
        );
    </script>

从上一节开始,您可以将代码自定义为您想要的格式

【讨论】:

You may find answer in the below code是什么意思?这是一个答案还是不是? 就是答案。我已经在我的项目中实现了它。

以上是关于Laravel Yajra 数据表呈现自定义 html / 列样式的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Datatable 中的按钮未呈现

如何在 yajra 数据表 laravel 中添加操作列

Laravel - Bootstrap 数据表(yajra)中的单选按钮

yajra/laravel-datatables 搜索不适用于 laravel 5.4

Laravel - Yajra Datatables 异常消息:试图获取非对象的属性

Laravel 5.7.9 中 Yajra 数据表中的删除按钮