New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support different API response structures (for pagination) #21
Comments
How about customize VuexORM.use(VuexORMAxios, {
http: {
onResponse(response) {
// For api with pagination
if (response.data && response.data.results) {
return response.data.results;
}
// For api without pagination
return response.data;
},
},
}); In my case data containing in |
I define different status codes in the Laravel controller. This allows more correct processing of query results. namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ArticleResource extends JsonResource
{
/**
* The "data" wrapper that should be applied.
*
* @var string
*/
public static $wrap = null;
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return parent::toArray($request);
}
} use Illuminate\Http\Response;
...
class ArticlesController extends Controller
{
public function index()
{
$articles = Article::with([
'categories:categories.id,categories.title,categories.slug',
'user:users.id,users.name',
])->withCount([
'comments',
'files',
])->paginate();
$collection = ArticleResource::collection($articles);
return $collection->response()
->setStatusCode(Response::HTTP_PARTIAL_CONTENT);
}
public function store(ArticleRequest $request)
{
...
->setStatusCode(Response::HTTP_CREATED);
}
public function show(int $id)
{
$article = Article::findOrFail($id);
// 200 Response::HTTP_OK
return new ArticleResource($article);
}
public function update(ArticleRequest $request, int $id)
{
...
->setStatusCode(Response::HTTP_ACCEPTED);
}
public function destroy(int $id)
{
...
return response()->json(null, Response::HTTP_NO_CONTENT);
} // store/index.js
...
// Import Vuex plugins.
import VuexORM from '@vuex-orm/core'
import VuexORMAxios from '@vuex-orm/plugin-axios'
import database from './database'
import http from './axios-request-config'
VuexORM.use(VuexORMAxios, {
http,
database,
})
... // store/axios-request-config.js
import store from '@/store'
import router from '@/router'
export default {
axios: undefined,
...
onResponse(response) {
const statuses = {
201: this.onCreatedResponse,
202: this.onUpdatedResponse,
204: this.onDeletedResponse,
206: this.onPartialContent,
}
return response.status in statuses
? statuses[response.status](response)
: response.data
},
...
/**
* On 206 Partial Content
* @param {object} response
*/
onPartialContent(response) {
const {
data,
meta
} = response.data
store.dispatch('paginator/paginate', meta)
router.replace({
query: {
'page': meta.current_page
}
})
return data
},
...
} // views\articles\index.vue
...
methods: {
async index(page = 1) {
// Reset resource list.
await this.model.deleteAll()
// Fetch article resource.
await this.model.$fetch({
query: {
page: parseInt(page, 10)
}
})
},
... |
@russsiq Awesome idea with the status codes. ...
store.dispatch('paginator/paginate', meta) // this module/action
... |
@malinushj, you can look here https://gist.github.com/russsiq/a6279e15bb0edee63d1da0e71839cba3 |
@russsiq Awesome! thank you! |
Useful for pagination. Related to issue vuex-orm#21
The brand new Axios plugin is here! It's very different from what it was, so please check out the docs! With the new version, there's config |
@kiaking bless |
@kiaking i still do not get it, how does this even help with the pagination? I want to store the full data and pagination aswell as i'm doing an infinite scrolling ... |
This is not directly related to the issue, but I'm writing here in case it might help someone else. When you do pagination (w/sort) you'll also need to know which elements belong on the "current page", but this plugin uses insertOrUpdate after fetching your "page" from the end-point, essentially adding the "first" and the "second" page when you navigate. What you have to do is is replace instead of insert. The only way to do that AFIK is to deleteAll() model. Unfortunately doing so will remove the items right away while waiting for the end-point to return (if ever and successfully). You can pass const result = await Job.api().get('/api/jobs', {save: false})
Job.deleteAll() // delete first
result.save() // this commits to store So by manually saving to store you don't get that bad UX where your list is empty while waiting for the next page. Other methods I've explored is instead saving the IDs for the current page that way you don't have to deleteAll() first. But instead you use the ORM to like |
Frameworks like Laravel often have built in pagination methods, which in turn change the default return data from the API.
plugin-axios
current$fetch
method requires that the model data is in the root of the response array, however Laravel's pagination method returns something like the following, with the data nested in the response:It is necessary that this data is paginated server side, as you can see there is a total of
16113
records, which in reality have many more columns and each have their own relationships.Would it be possible to cater for this by including some configuration (either globally or within each model, maybe even just as simple as
paginated: true
would be amazing) where you could specify the expected response structure, or key of the data or something? It would be great if the pagination keys could be stored too, although would not need to be queried in the same way as the data.At the moment I simply can't use this as half of my API routes return paginated data, which I'm sure is common. I've tested a route without it and it works perfectly so thank you for this, huge huge help with working with a large scale SPA.
Maybe even be as simple as changing this in
Fetch.js
from:To this:
But I'm unsure of what other side effects this may have or what exactly
insertOrUpdate
is expecting.Many thanks in advance.
EDIT: Have since tried the
insertOrUpdate
part in the promise returned from$fetch
, this got the data working great (albeit with an empty default record at index 0) but doesn't populate any of the pagination values, even after manually specifying the keys in each model's state.The text was updated successfully, but these errors were encountered: