Lazy data loading (infinite scroll)
Enabling lazy loading on the Scheduler makes it possible to load the different datasets in chunks when they rendered into view, instead of loading and replacing the datasets completely.
Before continuing reading, please read the Grid's lazy loading guide as it covers the basics of the lazy loading functionality.
There are two main paths to take when implementing lazy load support, either you use the CrudManager, or you do not.
Not using CrudManager
If you are not using the CrudManager, you will need to configure each store separately. Currently, these Scheduler stores supports lazy loading:
ResourceStore
The ResourceStore is used to populate the "rows" of the Scheduler. Please read the Grid's lazy loading guide for a detailed explanation of the basics of lazy loading which fully applies to the ResourceStore.
new Scheduler({
resourceStore : {
// This will create an AjaxStore
readUrl: 'backend/resources/read',
// This will activate the lazy load functionality
lazyLoad: true,
// This will load the Store initially upon creation
autoLoad: true
}
});
The other stores
Begin by setting the lazyLoad config on the Store to true to enable this
behaviour.
Using an AjaxStore
If your store is an AjaxStore you only need to configure the readUrl, and then you are done (at least on the frontend).
new Scheduler({
eventStore: {
// This will create an AjaxStore
readUrl: 'backend/events/read',
// This will activate the lazy load functionality
lazyLoad: true
}
});
Using a regular Store
If you are using a regular Store, then you will need to implement the requestData function with your own data loading logic. How this function is called is a little different depending on store type:
- For EventStore it is called when events for a resource in a certain timespan is requested, and has not yet been loaded.
- For AssignmentStore it is called when the EvenStore's requestData is called. It is
therefore not possible to have the EventStore's lazyLoad
falseand the AssignmentStore's lazyLoadtrue. - For TimeRangeStore it is called when the EvenStore's requestData is called. It is
therefore not possible to have the EventStore's lazyLoad
falseand the TimeRangeStore's lazyLoadtrue. - For ResourceTimeRangeStore it is called when resourceTimeRanges for a resource in a certain timespan is requested, and has not yet been loaded.
requestData will be called with a single object argument containing
a startIndex and a count value, and also a startDate and an endDate value. If the
ResourceStore is configured as a tree, startIndex
and count will be replaced by a resourceIds array. For a detailed explanation of these values, please read the
'Resource indexes and dates' chapter below.
class MyEventStore extends EventStore {
static configurable = {
lazyLoad: true
};
async requestData({
startIndex,
count,
startDate,
endDate
}) {
const response = await fetchData({
startIndex,
count,
startDate,
endDate
});
// The requestData function is expected to return an object
// with a data property, which value contains all the records
return {
data: response.data
}
}
}
new Scheduler({
eventStore: new MyEventStore()
});
ResourceStore as tree
If the ResourceStore is configured with
tree set to true there are some very important differences to know about:
- For the lazy load functionality to recognize that a store is expecting tree data, the
tree config must be set to
true. The autoTree config is not supported. - The isFullyLoaded field can be set from the backend, indicating that a
TreeNode should not initiate any more load requests. If omitted, it will be set to
trueautomatically when a load request returns a smaller number of children than asked for.
When using a Tree store, a load request will be made in the following scenarios:
- The initial load request, either by autoLoad or a separate load call.
- When a TreeNode is rendered and:
- it has expanded set to
trueand isFullyLoaded set tofalse - is the last child of a parent which has isFullyLoaded set to
false
- it has expanded set to
- A TreeNode with expanded set to
falseis manually or programmatically expanded
It is allowed, and in most cases recommended, to include nested data in the server responses. Please read more in the upcoming chapters.
Resource indexes and dates
For resources, the lazy loading depends on indexes to know what has been loaded and what has not. When it comes to events, resourceTimeRanges or assignments it is a bit more complicated. When a EventStore, for example, gets a request for events for a specified resource and a specified timespan, a load request will be made containing four parameters:
startIndex- The resource start indexcount- The resource countstartDate- The start date of the calculated timespanendDate- The end date of the calculated time span
If the ResourceStore is configured as a tree, or, the other store (i.e. the EventStore) is configured with useResourceIds the load request will contain these tree parameters instead:
resourceIds- An array of ids for every resource in the resource rangestartDate- The start date of the calculated timespanendDate- The end date of the calculated time span
If the ResourceStore has remote filters or sorters those will be applied to the
other stores requests as well. It will use the filterParamName or
sortParamName configured on the
ResourceStore as parameter name, but if they are identical to those configured on the
other store, the names will be prepended with the text "resource". For example, if
sortParamName is identical on both the
ResourceStore and the EventStore, a
sortParamName of sort will be changed to resourceSort, .
The dates will be calculated using the current visible (rendered) timespan as a base. The duration specified in the
Store's lazyLoad config's properties bufferUnit and bufferAmount will
be subtracted from the visible start date and added to the visible end date. These values default to the full visible
timespan length. If you are using a non-continuous timeaxis, you may have
to adjust these values manually.
This "two-dimensional" request range will then be remembered, so when a new request is made, the EventStore knows that it has or has not already loaded events for that range, and can act accordingly.
Sorting and filtering
Local sorting and filtering is not supported when the store is lazy loaded. Remote sorting and filtering, however, is supported. If you use an AjaxStore configured with remote sorting or filtering (which is done by setting filterParamName or sortParamName), the sorter and/or filter information will be available in the fetch request parameters.
If you do not use an AjaxStore, you should configure the Store with remoteSort
or remoteFilter. This will add a sorters and/or a filters param to the
requestData call.
A filter or a sort action on the Store will clear all loaded records and a new load request will be made. This is
because a sort or a filter action will change the record's indexes, which makes the loaded dataset invalid.
Backend
For each lazy load request you need to fetch records corresponding to the specified parameters:
- The record should have a
resourceIdin the resource range (startIndexandcount, or included inresourceIds). Ignore for timeRanges. - The record should either have a
startDateor anendDatein the date range (startDateandendDate).
If you are using AjaxStore, the response(s) need to look like this:
// Return the expected JSON response
res.json({
success: true,
data: events // Or timeRanges, or assignments etc...
});
Using CrudManager
When you are using the CrudManager, things are a bit simpler. Set the
lazyLoad to true and see to it that you have a
loadUrl configured. Also, you will either have to set
autoLoad to true or call the
load function manually.
new Scheduler({
crudManager: {
loadUrl: 'backend/events/read',
// This will activate the lazy load functionality
lazyLoad: true,
// This will initiate the first load upon creation
autoLoad: true,
}
});
The CrudManager will initiate a load request either when the ResourceStore requests more records or when the EventStore requests more records. Then it will perform a load request to the specified loadUrl and add the data from the response to the affected Stores.
Data for the Stores that currently has no lazy load support, can either be supplied in the first load request, or set manually.
Please read the chapter about Resource indexes and dates as it applies when using the CrudManager as well.
Backend
When implementing a backend that serves the CrudManager, you first need to read the CrudManager guide. Here is a simple example of a (pseudo) JavaScript read endpoint.
const {
startIndex,
count,
startDate,
endDate,
requestId
} = JSON.parse(params), // Params from the client
// Extracting the resources that's requested
resources = ALL_RESOURCES.slice(startIndex, startIndex + count),
resourceIds = resources.map(resource => resource.id),
// Extracting the events that's requested
events = ALL_EVENTS.filter(event => resourceIds.includes(event.resourceId)
&& ((event.startDate >= startDate && event.startDate < endDate)
|| (event.endDate > startDate && event.endDate <= endDate)));
return {
responseText : JSON.stringify({
success : true,
requestId,
events : loadEvents(startIndex, count, new Date(startDate), new Date(endDate)),
resources : loadResources(startIndex, count),
assignments : singleAssignments ? undefined : loadAssignments(startIndex, count, new Date(startDate), new Date(endDate)),
dependencies : { rows : [{ id : 1, from : 1, to : 2 }] }
})
};
The params which are sent to the backend also contains an array of ids of the Stores that is requested. On
the first load, all stores managed by the CrudManager will be included in the array.
After that, only the lazy load supported stores will be included. If the timespan of the Scheduler changes, a request
will be initiated from the EventStore, and in those requests the stores param will
exclude the ResourceStore as well. You need not provide data for stores that is not
present in the stores param.
Not supported
There is a number of Scheduler features, functions and configs that is either not supported at all or only works in a limited way. Such information is available in the corresponding documentation. Please note that support will continuously be added where it makes sense to be added. Please let us know of the functionality that lacks support and is most important to you.
LazyLoading is currently not supported in Calendar, Gantt nor TaskBoard.