Skip to content

Commit 759d47e

Browse files
committed
docs: provide Laravel integration instructions
1 parent ac70ed3 commit 759d47e

File tree

1 file changed

+172
-1
lines changed

1 file changed

+172
-1
lines changed

README.md

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* [Set up](#set-up)
1212
* [Usage](#usage)
1313
* [Nuxt integration](#nuxt-integration)
14+
* [Laravel integration](#laravel-integration)
1415
* [CONFIGURATION](#configuration)
1516
* [Columns](#columns)
1617
* [Custom Cell Component](#custom-cell-component)
@@ -19,6 +20,7 @@
1920
* [Selectable rows](#selectable-rows)
2021
* [Text](#text)
2122
* [Adding Language](#adding-language)
23+
* [Async data](#async-data)
2224
* [Layout](#layout)
2325
* [Custom Components](#custom-components)
2426
* [Footer](#footer)
@@ -48,6 +50,7 @@ that automatically generates beautiful forms from declarative rules.
4850
- Custom Footer to display data summary
4951
- Support for Vue3 and Vue2
5052
- Nuxt integration
53+
- Laravel integration
5154

5255
## DEMO
5356

@@ -128,9 +131,17 @@ export default defineNuxtPlugin(nuxtApp => {
128131

129132
Nuxt automatically loads the files in the `plugins/` directory by default.
130133

134+
### Laravel integration
135+
136+
This plugin integrates with Laravel's pagination API, so it fetches data
137+
asynchronously from the provided URL. Follow the instrunctions in the
138+
[async data section](#async-data) for a detailed setup.
139+
131140
## CONFIGURATION
132141

133-
Only `data` e `columns` are required. Other props are optional.
142+
Only `columns` are required. Other props are optional.
143+
144+
If `data` is not passed, then `fetchUrl` and `fetchCallback` *must* be passed.
134145

135146
`vKey` is not required but is **highly** recommend to set it if you plan to
136147
add or delete rows in the table!
@@ -144,6 +155,8 @@ add or delete rows in the table!
144155
| lang | `String` | `en` | The default language |
145156
| perPageSizes | `Array` | [10, 25, 50, 100, '*'] | The options for the number of rows being displayed per page. The string '*' shows all. |
146157
| defaultPerPage | `Number` | 10 | The default number of entries. If unset, then it will be the first value of `perPageSizes` |
158+
| fetchUrl | `String` | - | The URL to fetch data from if `data` is null |
159+
| fetchCallback | `String` | - | Async function which takes an URL and returns `data` matching Laravel's pagination API |
147160
| isLoading | `Bool` | `false` | Whether table data is loading. Table rows are shown only if this value is set to `false` |
148161
| loadingComponent | `String`, `Object` | - | VueJS component to be shown if `isLoading` is set to `true` |
149162
| showPerPage | `Bool` | `true` | Whether to show the `PerPage` component |
@@ -664,6 +677,163 @@ reflect the changes globally. For example:
664677
languageServiceProvider.setLangText("en", "downloadText", "download as:")
665678
```
666679

680+
681+
### Async data
682+
683+
If you do not want to fetch all data at once and pass it to `VueDataTable` via
684+
the `data` prop, you can do so by defining:
685+
686+
- `fetchUrl`: initial endpoint for the first ajax request to fetch data
687+
- `fetchCallback`: async function which takes an URL and returns a response
688+
following Laravel's pagination API.
689+
690+
Here is a sample `fetchCallback`:
691+
692+
```vue
693+
<template>
694+
<h1>Users</h1>
695+
<vue-data-table v-bind="vdtProps" />
696+
</template>
697+
<script setup>
698+
const vdtProps = {
699+
columns: [
700+
{ key: 'name' },
701+
{ key: "email", title: "Email address" },
702+
],
703+
fetchUrl: "http://app.test/api/users",
704+
fetchCallback: async (url) => fetch(url).then(response => response.json())
705+
}
706+
</script>
707+
```
708+
709+
The example above uses the browser's built-in `fetch`, but you can also use
710+
`axios` or Nuxt's `$fetch` under the hood. Just make sure the response returned
711+
by the callback matches the following.
712+
713+
The response from the `fetchCallback` should look like this:
714+
715+
```jsonc
716+
{
717+
"data": [
718+
{ "id": 1, "name": "Miss Juliet Heidenreich", "email": "[email protected]"},
719+
{ "id": 2, "name": "Heloise Boehm", "email": "[email protected]"},
720+
{ "id": 3, "name": "Antwon Collins", "email": "[email protected]},
721+
/* ... */
722+
],
723+
"current_page": 1,
724+
"first_page_url": "http://app.test/api/users?page=1",
725+
"from": 1,
726+
"last_page": 23,
727+
"last_page_url": "http://app.test/api/users?page=23",
728+
"links": [
729+
{ "url": null, "label": "&laquo; Previous", "active": false },
730+
{ "url": "http://app.test/api/users?page=1", "label": "1", "active": true },
731+
{ "url": "http://app.test/api/users?page=2", "label": "2", "active": false },
732+
{ "url": "http://app.test/api/users?page=3", "label": "3", "active": false },
733+
/* ... */
734+
{ "url": "http://app.test/api/users?page=23", "label": "23", "active": false },
735+
{ "url": "http://app.test/api/users?page=2", "label": "Next &raquo;", "active": false }
736+
],
737+
"next_page_url": "http://app.test/api/users?page=2",
738+
"path": "http://app.test/api/users",
739+
"per_page": 15,
740+
"prev_page_url": null,
741+
"to": 15,
742+
"total": 340
743+
}
744+
```
745+
746+
Here is how you do so in Laravel:
747+
748+
```php
749+
<?php
750+
751+
use App\Models\User;
752+
use Illuminate\Support\Facades\Route;
753+
754+
Route::get('users', function () {
755+
return User::paginate();
756+
});
757+
```
758+
759+
This will also work with collections: `new UserCollection(User::paginate())`.
760+
761+
In order to be able to **sort** and **search** using endpoints compatible with
762+
Laravel's API, this plugin provides support for Spatie's Laravel Query Builder
763+
package, which allows you to easily generate API endpoints with sorting and
764+
searching functionalities with well-defined standard.
765+
766+
```php
767+
<?php
768+
769+
use App\Models\User;
770+
use Illuminate\Support\Facades\Route;
771+
use Spatie\QueryBuilder\QueryBuilder;
772+
773+
Route::get('users', function () {
774+
return QueryBuilder::for (User::class)
775+
->allowedSorts(['name', 'email'])
776+
->allowedFilters(['name', 'email'])
777+
->paginate();
778+
});
779+
```
780+
781+
The endpoints look like this:
782+
783+
- `http://app.test/api/users?page=1&filter[name]=foo`
784+
- `http://app.test/api/users?page31&sort=job,-email`
785+
- `http://app.test/api/users?page=1&sort=email&filter[email]=joe&filter=[name]=joe`
786+
787+
You do **not** need to worry about the URLs if you are using Spatie's Laravel Query Bulder,
788+
because `VueDataTable` follows their endpoint standard and automatically generates the urls.
789+
790+
If you do not use their package, then you should parse the `url` variable inside
791+
the `fetchCallback`, and modify the url. For example, your javascript code should modify:
792+
793+
`http://app.test/api/users?page=4&filter[name]=foo --> http://app.test/api/users?page=4&search=foo`.
794+
795+
Keep in mind that, by default, Spatie's Query Builder apply AND logic for all
796+
filters. That means if you have `&filter[name]=Ana&filter[email]=Ana`, then
797+
you will only get results that both `name` and `email` fields match Ana. If
798+
`name` matches Ana but not the `email` column, then this row would not appear.
799+
800+
Here is how you can implement `OR` logic using their package:
801+
802+
```php
803+
<?php
804+
805+
// routes/app.php
806+
use App\Http\Filters\FilterOrWhere;
807+
use App\Models\User;
808+
use Illuminate\Support\Facades\Route;
809+
use Spatie\QueryBuilder\QueryBuilder;
810+
use Spatie\QueryBuilder\AllowedFilter;
811+
812+
Route::get('users', function () {
813+
return QueryBuilder::for (User::class)
814+
->allowedSorts(['name', 'email'])
815+
->allowedFilters([
816+
AllowedFilter::custom('name', new FilterOrWhere),
817+
AllowedFilter::custom('email', new FilterOrWhere)
818+
])
819+
->paginate();
820+
});
821+
822+
// app/Http/Filters/FilterOrWhere.php
823+
namespace App\Http\Filters;
824+
825+
use Spatie\QueryBuilder\Filters\Filter;
826+
use Illuminate\Database\Eloquent\Builder;
827+
828+
class FilterOrWhere implements Filter
829+
{
830+
public function __invoke(Builder $query, $value, string $property)
831+
{
832+
$query->orWhere($property, 'LIKE', '%' . $value . '%');
833+
}
834+
}
835+
```
836+
667837
### Layout
668838

669839
`VueDataTable` uses CSS's grid display to specify the position of its components
@@ -939,6 +1109,7 @@ export default {
9391109
## ROADMAP
9401110
9411111
- [x] Support for Vue3
1112+
- [x] Laravel integration
9421113
- [ ] Support for SSR
9431114
- [ ] String notation for defining columns
9441115

0 commit comments

Comments
 (0)