drupal approved pagination
AtRiskMedia opened this issue · 3 comments
Hi, thanks so much for this amazing library!
The drupal docs are very clear: "If you take only one thing away from this guide, it should be that you should not construct your own pagination URLs", https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module/pagination
I see there's a module to allow override: https://www.drupal.org/project/jsonapi_page_limit but i'm hoping to avoid this
Is there any way to access the "links" next and count on the response from Drupal?
I'd like to run successive fetches in a recursive loop but could only do this using .addPageOffset
Is there a better pattern to follow?
this what's working for me (in astro):
- construct the first query, e.g. get all article nodes
- on the first fetch i intercept the response. If the links.next.href is present, i'll loop and then combine all the data and return the full payload.
import { Jsona } from "jsona";
import { DrupalJsonApiParams } from "drupal-jsonapi-params";
import type { DrupalFile, DrupalNode } from "../types.ts";
import type { TJsonApiBody, TJsonaModel } from "jsona/lib/JsonaTypes";
interface DrupalApiBody extends TJsonApiBody {
/* eslint-disable @typescript-eslint/no-explicit-any */
links?: any;
}
export const baseUrl: string = import.meta.env.DRUPAL_BASE_URL;
export const fetchUrl = async (url: string): Promise<any> => {
let data: TJsonaModel = [];
let more = true;
while (more) {
const request: Response = await fetch(url);
const json: string | DrupalApiBody = await request.json();
const dataFormatter: Jsona = new Jsona();
const thisData = dataFormatter.deserialize(json);
if (thisData.length) data = data.concat(thisData);
else data.push(thisData);
url = typeof json !== `string` ? json?.links?.next?.href : null;
if (typeof url === `undefined`) more = false;
}
return data;
};
export const getFiles = async (): Promise<DrupalFile[]> => {
const params: DrupalJsonApiParams = new DrupalJsonApiParams();
params.addFields("file--file", ["type", "id"]).addFilter("status", "1");
const path: string = params.getQueryString();
return await fetchUrl(baseUrl + "/jsonapi/file/file?" + path);
};
export default fetchUrl;
@AtRiskMedia am glad that you found this module helpful and thanks for sharing your concern regarding pagination.
ATM, the module only provide a helper method generate your query. It is independent of result. It works with no Feedback. Keeping it independent of how the actual query is executed (fetch, axios, XMLHttpRequest...) helps keep it framework agnostic.
If we have to continue on this, then to get dynamic next
links based on results, we would have to feed the current result into DrupalJsonApiParams
and call some method like next
get the url , fire the query, get the result feed it back to DrupalJsonApiParams
and repeat ... I don't think it as a nice developer experience over what you have achieved in your sample code.
What you have done is a really a nice pattern to follow none the less. Alternatively, we can add this to project documentation (in README.md) so that people can benefit from this.
What do you think?
Awesome. Thanks @d34dman ... yes, even a quick note in the docs suggesting this as a pattern may be helpful for others.
Using DrupalJsonApiParams to craft the endpoint then follow the payload for subsequent urls to adhere to Drupal pagination: It's best of both worlds.