jQuery DataTables,自定义服务器端排序

9
我正在使用 Laravel 4.2,配合服务器端的 jQuery 数据表格。
包:https://github.com/Chumper/Datatable 我该如何添加自定义排序?
例如对于货币、时间等列。

使用类似这个的怎么样 https://github.com/lazymofo/datagrid,或者用这个扩展 https://github.com/ais-one/datagrid_ext - Aaron Gong
@AaronGong,还有其他选择可用,但我已在几个页面上集成了datatables,不想重写。 - Riz
好的,祝你好运。我也看了datatables和其他一些类似的CRUD工具,最终选择了lazymofo datagrid。 - Aaron Gong
5个回答

0

注意:此处未使用Chumper / Datatable软件包,但是它确实使用了jQuery datatables,因此可能会有所帮助。

以下是我执行此操作的方法。这是一个场景,其中我有一张包含美式足球队伍的表格。每个队伍都是会议的成员,并且该会议属于某个分区。可以按照团队名称、会议或分区对团队进行排序。以下是用于实现此功能的服务器端代码。此外,也可以通过会议或分区进行过滤。

/*
 * Route::get( 'api/v1/teams-table', 'APIController@teamsTable' );
 */
public function dataTable() {
    // get the input parameters
    $i = Input::all();

    // parse the parameters and set default values
    $draw   = isset( $i[ 'draw'   ] ) ? $i[ 'draw'   ] : 1;
    $start  = isset( $i[ 'start'  ] ) ? $i[ 'start'  ] : 0;
    $length = isset( $i[ 'length' ] ) ? $i[ 'length' ] : 10;
    $search = isset( $i[ 'search' ][ 'value' ] ) && '' != $i[ 'search' ][ 'value' ] ? $i[ 'search' ][ 'value' ] : false;
    $ordrby = isset( $i[ 'order'  ] ) ? $i[ 'columns' ][ $i[ 'order' ][ 0 ][ 'column' ] ][ 'name' ] : '';
    $ordrdr = isset( $i[ 'order'  ] ) ? $i[ 'order' ][ 0 ][ 'dir' ] : 'asc';
    $total  = Team::count();
    $filter = $total;


    // get the data
    if ( '' == $search ) {
        switch( $ordrby ) {
            case 'name':
                $teams = Team::with( 'conferences', 'logo', 'conferences.division' )
                    ->skip( $start )
                    ->take( $length )
                    ->orderBy( 'name', $ordrdr )
                    ->get();
                break;
            case 'conference':
                $teams = Team::with( 'conferences', 'logo', 'conferences.division' )
                    ->join( 'conference_team', 'conference_team.team_id', '=', 'teams.id' )->join( 'conferences', 'conferences.id', '=', 'conference_team.conference_id' )
                    ->orderBy( 'conferences.abbr', $ordrdr )
                    ->skip( $start )
                    ->take( $length )
                    ->get();
                break;
            case 'division':
                $teams = Team::with( 'conferences', 'logo', 'conferences.division' )
                    ->skip( $start )
                    ->take( $length )
                    ->conference()
                    ->division()
                    ->orderBy( 'abbr', $ordrdr )
                    ->get();
                break;
            default:
                $teams = Team::with([ 'conferences', 'logo', 'conferences.division' ])
                    ->skip( $start )
                    ->take( $length )
                    ->get();
        }
    } else {
        $teams = Team::with( 'conferences', 'logo', 'conferences.division' )
            ->skip( $start )
            ->take( $length )
            ->where( 'name', 'LIKE', '%' . $search . '%' )
            ->orWhereHas( 'conferences', function( $q ) use ( $search ) { 
                $q->where( 'abbr', 'LIKE', '%' . $search . '%' )
                    ->orWhereHas( 'division', function( $qu ) use ( $search ) {
                        $qu->where( 'abbr', 'LIKE', '%' . $search . '%' );
                    }); 
            })
            ->get();
        $filter = Team::with( 'conferences', 'logo', 'conferences.division' )
            ->where( 'name', 'LIKE', '%' . $search . '%' )
            ->orWhereHas( 'conferences', function( $q ) use ( $search ) { 
                $q->where( 'abbr', 'LIKE', '%' . $search . '%' )
                    ->orWhereHas( 'division', function( $qu ) use ( $search ) {
                        $qu->where( 'abbr', 'LIKE', '%' . $search . '%' );
                    }); 
            })
            ->count();
    }

    // loop through the retrieved data and format it to be returned as JSON
    $data = [];
    foreach ( $teams as $t ) {
        $show = URL::route( 'admin.team.show', $t->slug );
        $edit = URL::route( 'admin.team.depth_chart', $t->slug );
        $data[] = [
            'checkbox'   => '<label><input type="checkbox" class="ace" value="' . $t->id . '" /><span class="lbl"></span></label>',
            'logo'       => '<img src="' . $t->logo->filename . '" alt="' . $t->name . ' logo" height="40">',
            'name'       => [
                'display' => link_to_route( 'admin.team.show', $t->name, [ $t->slug ] ),
                'filter'  => $t->name,
                'sort'    => $t->name,
            ],
            'conference' => [
                'display' => link_to_route( 'admin.conference.show', $t->conferences[ 0 ]->abbr, [ $t->conferences[ 0 ]->slug ] ),
                'filter'  => $t->conferences[ 0 ]->name . ' ' . $t->conferences[ 0 ]->abbr,
                'sort'    => $t->conferences[ 0 ]->abbr,
            ],
            'division'   => [
                'display' => link_to_route( 'admin.division.show', $t->conferences[ 0 ]->division->abbr, [ $t->conferences[ 0 ]->division->slug ] ),
                'filter'  => $t->conferences[ 0 ]->division->name . ' ' . $t->conferences[ 0 ]->division->abbr,
                'sort'    => $t->conferences[ 0 ]->division->abbr,
            ],
            'site'       => '<a target="_blank" href="' . $t->url . '">website <i class="fa fa-external-link"></i></a>',
            'actions'    => sprintf( $this->actions, $show, $edit, $show, $edit ),
        ];
    }

    $tdata = [
        'draw'            => $draw,
        'recordsTotal'    => $total,  //consider caching or setting fixed value for this
        'recordsFiltered' => $filter,
        'data'            => $data,
    ];

    return Response::json( $tdata );
}

希望你能幸运地调整这个例子以适应你的情况。希望这可以帮到你!


0

这是我的做法

注意:它并没有进行优化,基本上是一个完整的代码片段,没有错误检查

Laravel控制器函数(适用于L5.2,但可以轻松降级到4.2):

    $response = array();
    $query = MyModel::query();

    $response['recordsTotal'] = MyModel::count();
    $response['draw'] = Input::get('draw', 0);

    $query->where('searchField', 'LIKE', '%' . Input::get('search', array('value' => ''))['value'] . '%');
    $response['recordsFiltered'] = $query->count();

    $query->take(Input::get('length', 1));
    $query->offset(Input::get('start', 0));


    $columns = Input::get('columns');
    $orders = Input::get('order', []);

    $data = $data->toArray();
    foreach($orders as $order){
        $idx = $order['column'];
        $column = $columns[$idx];

        $orderFactor = 1;
        if($order['dir'] == 'desc')
            $orderFactor = -1;
        $dname = $column['data'];
        if(count($data)>0){
            if(isset($data[0][$dname])){
                usort($data, function($record1, $record2) use($dname, $orderFactor){
                    // here you implement your custom sorting
                    // like if($dname === 'price') return compare_price($record1[$dname], $record2[$dname]) * $orderFactor; 
                    // but I hope you're not storing prices as strings in your database. you won't need this custom sorting
                    //
                    return strcmp($record1[$dname], $record2[$dname]) * $orderFactor;
                });
            }
        }
    }
    $response['data'] = $data;
    return Response::json($response);

注:此代码假设数据表列的“data”字段与您的数据库中的字段名完全相同。 您还需要使用render_function按照您的意愿呈现datatable列。

数据表列:

columns: [
    { data: 'price', orderable: true, searchable: true, render: render_price },
    { data: 'anotherField' },
    [...]
],

render_function 例子:

    function render_price(price, type, row) {
        return price + ' USD';
    }

这样,您就可以按照自己的要求显示数据表列(例如:价格=10.50美元)

并且它们将是可排序的。


0

如果你想按任意顺序对集合或查询结果进行排序,可以这样做:

$orders = Order::all()->SortBy('currency','desc');

或者

$customers = Customers::where('age',$age)->orderBy('currency','desc')->get();

顺便问一下,既然 Laravel 8 已经发布了,为什么你还在使用 Laravel 4 呢?

1
顺便问一下,既然 Laravel 8 已经发布了,你为什么还在使用 Laravel 4?这个问题已经存在六年了吗? - miken32

-1

不确定你所说的自定义排序是指按表头点击对行进行排序吗?如果是这样,那么你可以通过定义数据表设置来在客户端上定义它们。

oSettings = $("#{{$table->getId()}}").dataTable().fnSettings();
oSettings.aaSorting = [[6, 'desc']];

但是,如果您想在数据表加载时保持特定列的默认排序,则

Datatable::table()
        ->addColumn($theader)       // these are the column headings to be shown
        ->setOptions('order', array([$ordercolumn ,"desc"]))
        ->setUrl(route('route.name', $form_id))   
        ->render()

希望这能有所帮助。


-4
你有没有查看文档?因为里面已经解释了:
public function getDatatable() { return Datatable::collection(User::all(array('id','name'))) ->showColumns('id', 'name') ->searchColumns('name') ->orderColumns('id','name') ->make(); }

我在询问自定义排序,而不是列顺序或其他任何内容。如果您的答案中有自定义排序,请告诉我在哪里。 - Riz
你所说的自定义排序是什么意思?请给出更好的解释或示例。 - cre8
https://www.datatables.net/plug-ins/sorting/currency - 这是用于客户端 JS 解决方案的插件,我正在寻找相同的服务器端解决方案。 - Riz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接