How to create a custom data source with support for paging?

Hi there,

I am attempting to use the Syncfusion data grid to display paged (only pulling each page as needed, not all at once) data retrieved from an AWS Amplify GraphQL provider. Amplify generates Javascript helpers for accessing the data so a direct interface from the grid to GraphQL isn't necessary, just the ability to manually call promise based Javascript methods. I'm having trouble finding any way to do this. Nearly everything I've found online points to one of two methods: Create a custom adaptor and use it with DataManager or handle the DataStateChange event manually. I've tried both methods and run into issues with them.

Custom Adaptor

Here's the code for my grid component:

<template>
  <div>
    <ejs-grid :dataSource="data">
      <e-columns>
        <e-column field="Name" headerText="Name"></e-column>
        <e-column field="Description" headerText="Description"></e-column>
      </e-columns>
    </ejs-grid>
  </div>
</template>

<script>
import { DataManager } from '@syncfusion/ej2-data';
import CustomAdaptor from '@/utils/customAdaptor';

export default {
  name: 'MyList',
  provide: {
    grid: [CommandColumn]
  },
  data() {
    return {
      data: new DataManager({
        adaptor: new CustomAdaptor()
      })
    }
  }
}
</script>

And the custom adaptor (latest a:

import { Adaptor } from "@syncfusion/ej2-data";
import { API, graphqlOperation } from 'aws-amplify';

import * as queries from '@/graphql/queries';

export default class CustomAdaptor extends Adaptor {
  async processQuery() {
    return API.graphql(graphqlOperation(queries.listMyData));
  }

  processResponse() {
    //calling base class processResponse function
    let original = super.processResponse.apply(this, arguments);
    console.log(original);
    return { result: original.result, count: original.count };
  }

The problem here is that processResponse seems to get called immediately and the promise returned by API.graphql doesn't get resolved. I also tried awaiting the call in processQuery with no luck. From reading everything online (docs, and forum responses) it appears there is no way to inject custom code to actually get the data, just to adjust the query and adjust the final data.

DataStateChange

I tried a couple of different methods for this (found in different places online)

Try 1

<template>
  <div>
    <h1>Sound Fonts</h1>
    <ejs-grid :dataSource="data" @dataStateChange="dataStateChange" @load="initialLoad" :allowPaging="true" :pageSettings="pageSettings">
      <e-columns>
        <e-column field="name" headerText="Name"></e-column>
        <e-column field="description" headerText="Description"></e-column>
      </e-columns>
    </ejs-grid>
  </div>
</template>

<script>
import { Page } from '@syncfusion/ej2-vue-grids';
import { API, graphqlOperation } from 'aws-amplify';
import * as queries from '@/graphql/queries';

export default {
  name: 'SoundFontsList',
  provide: {
    grid: [Page]
  },
  data() {
    return {
      data: [],
      pageSettings: { pageSize: 5 }
    }
  },
  methods: {
    dataStateChange: async function(args) {
      const result = await API.graphql(graphqlOperation(queries.listSoundFonts));
      this.data = result.data.listSoundFonts.items;
    },
    initialLoad: async function() {
      const result = await API.graphql(graphqlOperation(queries.listSoundFonts));
      this.data = result.data.listSoundFonts.items;
    }
  }
}
</script>

The problem here is that the data from the initialLoad method appears but I can't figure out how to tell the pager what the total number of entries is (without pulling all the data which is what this code is doing) so that it can properly show the page count, etc.

Try 2

<template>
  <div>
    <h1>Sound Fonts</h1>
    <ejs-grid :dataSource="data" @dataStateChange="dataStateChange" @load="initialLoad" :allowPaging="true" :pageSettings="pageSettings">
      <e-columns>
        <e-column field="name" headerText="Name"></e-column>
        <e-column field="description" headerText="Description"></e-column>
      </e-columns>
    </ejs-grid>
  </div>
</template>

<script>
import { Page } from '@syncfusion/ej2-vue-grids';
import { API, graphqlOperation } from 'aws-amplify';
import * as queries from '@/graphql/queries';

export default {
  name: 'SoundFontsList',
  provide: {
    grid: [Page]
  },
  data() {
    return {
      data: { results: [], count: 0 },
      pageSettings: { pageSize: 5 }
    }
  },
  methods: {
    dataStateChange: async function(args) {
      const result = await API.graphql(graphqlOperation(queries.listSoundFonts));
      this.data.results = result.data.listSoundFonts.items;
      this.data.count = result.data.listSoundFonts.items.length;
    },
    initialLoad: async function() {
      const result = await API.graphql(graphqlOperation(queries.listSoundFonts));
      this.data.results = result.data.listSoundFonts.items;
      this.data.count = result.data.listSoundFonts.items.length;
    }
  }
}
</script>

In this situation, the grid never shows any data.

Any help in finding the correct path would be greatly appreciated as I've spent way too much time on this already.

Thanks,
Jason

2 Replies

JL Jason Lee September 7, 2020 03:00 PM UTC

Quick note, in DataStateChange, Try 2, the data field is actually "result", not "results". I tried editing the post but the form either won't show the code or the Submit button didn't work.


MS Manivel Sellamuthu Syncfusion Team September 8, 2020 02:29 PM UTC

Hi Jason, 

Greetings from Syncfusion support. 

Custom Adaptor 

Currently, we do not have support for GraphQL with dataManager. we have already considered “GraphQL support for Essential JS 2 DataManager” as feature and added to our feature request list. It will be implemented in any of any upcoming releases. You can track the current status of this request, review the proposed resolution timeline, and contact us for any further inquiries through the following link, 
 

Custom Binding(DataStateChange) 

Try 1: 

While using custom binding, Grid expects an object as the result of the custom logic and the emitted value should be an object with properties result and count. So this method will not work properly. 

Try 2: 

As per your last  update, we could see that you are proving the dataSource for the Grid as result and count, which is the correct way to use custom binding. Please refer the below documentation and sample for more information. 



However we suspect that the data was not bound to the Grid properly. Could you please share the below details, which will be helpful for us to validate further about issue. 

  1. Share the use of async and await (We would like to inform you that inside the dataStateChange event, you can call your own api/service and in that success event of the api/service you can bind the resulted data as result and count format)
  2. Please place a debugger in the dataState change event and try hovering the variables having the expected value and share the screenshots to us.
  3. Share the screenshot or video demo of the issue
  4. Please bind the actionFailure event and share the network tab requests

Regards, 
Manivel 


Loader.
Up arrow icon