Skip to content

drupal approved pagination #40

Description

@AtRiskMedia

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?

Activity

  1. AtRiskMedia commented on Mar 6, 2024

    @AtRiskMedia
    Author

    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;
    
  2. d34dman commented on Mar 10, 2024

    @d34dman
    Owner

    @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?

  3. AtRiskMedia commented on Mar 11, 2024

    @AtRiskMedia
    Author

    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.

  4. added a commit that references this issue on Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions