таблицы данных jquery, настраиваемая сортировка на стороне сервера

Я использую Laravel 4.2 с таблицами данных jQuery на стороне сервера.

Пакет: https://github.com/Chumper/Datatable

Как добавить произвольную сортировку?

например, для столбцов валюты, времени и т. д.


person Riz    schedule 09.10.2015    source источник
comment
Как насчет того, чтобы использовать что-то подобное вместо github.com/lazymofo/datagrid или расширить его с помощью этого github.com/ais-one/datagrid_ext   -  person Aaron Gong    schedule 20.10.2015
comment
@AaronGong Есть и другие варианты, но у меня есть таблицы данных на нескольких страницах, и я не хочу переписывать.   -  person Riz    schedule 20.10.2015
comment
хорошо, тогда удачи, я тоже смотрел на таблицы данных и несколько других подобных примитивов, в итоге получился lazymofo datagrid.   -  person Aaron Gong    schedule 20.10.2015


Ответы (5)


ПРИМЕЧАНИЕ: при этом не использовался пакет Chumper / Datatable, но он использует таблицы данных jQuery, поэтому может быть полезным.

Вот как я это сделал. Это был сценарий, в котором у меня был стол с командами по американскому футболу. Каждая команда была членом Конференции, которая была частью Дивизиона. Команды можно было отсортировать по названию, конференции или подразделению. Ниже приведен код на стороне сервера, используемый для реализации этого. Кроме того, они могут быть отфильтрованы по конференциям или подразделениям.

/*
 * 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 );
}

Если повезет, вы можете скорректировать этот пример в соответствии с вашей ситуацией. Надеюсь это поможет!

person morphatic    schedule 16.10.2015

вот как я это делаю

n.b. это не оптимизировано. более или менее полный фрагмент кода без проверки ошибок

функция контроллера 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);

p.s. этот код предполагает, что поле '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 $)

и они будут отсортированы

person nonsensei    schedule 11.05.2016

Если вы пытаетесь отсортировать коллекцию или результат запроса в любом порядке, вы можете сделать что-то вроде этого:

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

or

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

Кстати, почему вы все еще используете Laravel 4, когда уже есть Laravel 8?

person AdekunleCodez    schedule 11.06.2021

Не уверены, что под custom sorting вы имеете в виду сортировку строк, нажимая на заголовки? Если вы это имеете в виду, вы можете определить их на стороне клиента, задав параметры данных.

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()

Надеюсь, это поможет.

person Abishek    schedule 19.10.2015

Вы не проверили документацию? Потому что там объясняется:

public function getDatatable() { return Datatable::collection(User::all(array('id','name'))) ->showColumns('id', 'name') ->searchColumns('name') ->orderColumns('id','name') ->make(); }
person cre8    schedule 09.10.2015
comment
Я спрашиваю о пользовательской сортировке, а не о порядке столбцов или о чем-то еще. Дайте мне знать, где в вашем ответе пользовательская сортировка. - person Riz; 12.10.2015
comment
Что вы имеете в виду под пользовательской сортировкой? Пожалуйста, дайте более подробное объяснение или пример. - person cre8; 12.10.2015
comment
datatables.net/plug-ins/sorting/currency - это для клиента конец решения JS, я ищу то же самое на стороне сервера. - person Riz; 12.10.2015