ratiw / vue-table

data table simplify! -- vuetable is a Vue.js component that will automatically request (JSON) data from the server and display them nicely in html table with swappable/extensible pagination component.
MIT License
1.83k stars 303 forks source link

Laravel5.3 filter relationships #79

Open roulendz opened 8 years ago

roulendz commented 8 years ago

I can not figue out how to filter eloquent relationships.

I have event, inside witch I have school_id, lesson_id, student_id. And I want to be able to filter, event.lesson.title, or event.school.title

How I can do it? web.php

Route::get('api/appointments', function() {
$request = request();

// handle sort option
if (request()->has('sort')) {
    list($sortCol, $sortDir) = explode('|', request()->sort);
    $query = App\Event::orderBy($sortCol, $sortDir)
    ->with('school')
    ->with('student')
    ->with('lesson')
    ->with('model');
} else {
    $query = App\Event::orderBy('id', 'asc')
    ->with('school')
    ->with('student')
    ->with('lesson')
    ->with('model');
}

if ($request->exists('filter')) {
    $query->where(function($q) use($request) {
        $value = "%{$request->filter}%";
        $q->where('lesson.public_title', 'like', $value)
            ->orWhere('model.name', 'like', $value)
            ->orWhere('school.title', 'like', $value);
    });
}

$perPage = request()->has('per_page') ? (int) request()->per_page : null;

// The headers 'Access-Control-Allow-Origin' and 'Access-Control-Allow-Methods'
// are to allow you to call this from any domain (see CORS for more info).
// This is for local testing only. You should not do this in production server,
// unless you know what it means.
return response()->json(
        $query->paginate($perPage)
    )
    ->header('Access-Control-Allow-Origin', '*')
    ->header('Access-Control-Allow-Methods', 'GET');
});

vuetable.js

// fields definition
var tableColumns = [
{
    name: 'start',
    title: 'Date',
    sortField: 'Date',
    callback: 'formatDate'
},
{
    name: 'lesson.public_title',
    title: 'Procedure',
    sortField: 'lesson.public_title',
},
{
    name: 'model.name',
    title: 'Model',
    sortField: 'odel.name',
},
{
    name: '__actions',
    title: '',
    titleClass: 'text-center',
    dataClass: 'text-center',
}
]
ratiw commented 8 years ago

@roulendz You have to use join to explicitly join the related tables, then you'll have access to the related table's underlying columns. Then, you make a alias column out of it.

  $query = User::join('groups', 'user.group_id', '=', 'group.id')
    ->select(['users.*', 'groups.name as group_name']
    ->paginate();

You will then have additional column named group_name and your can filter it as well. Then, you can tell vuetable to use that column as a sort field. This will make it sortable on vuetable as well.

// fields definition
var tableColumns = [
    {
        name: 'start',
        title: 'Date',
        sortField: 'Date',
        callback: 'formatDate'
    },
    {
        name: 'group_id',
        title: 'Group',
        sortField: 'group_name'   // <-- specify the sort field to use here
    }
    {
        name: '__actions',
        title: '',
        titleClass: 'text-center',
        dataClass: 'text-center',
    }
]
minedun6 commented 7 years ago

Hi, The data structure is the same as a Laravel pagination that I return from the server. But already sorted it out.