A collection is a client-side abstraction for the latest-saved server state of a list of objects (a model, by contrast, represents a single persisted object in that resource). A collection must have one thing:
a url
. This instance property can be a string literal or a function.
class MyTodos extends Collection<ModelType> {
url = '/todos'
}
class MyTodos extends Collection<ModelType> {
url({subtype}) {
return `/todos/${subtype}`;
}
}
A collection instance of the class created and registered in your resourcerer config will be returned by every useResources
call that uses its model key from the ModelMap. You can read simply from it
by using Collection#toJSON
(the most common usage), but there are several other methods and properties in its interface you can customize in your collection definition or
that you might find useful in rendering your data-hydrated components.
Add this on your Collection definition to tell it how it should sort its models. It can take three forms:
- A string. In this case, it represents the model property to sort by.
- A function with a single argument. In this case, it takes a model's data as an argument and returns the value by which it should sort.
- A function with two arguments. This is used to sort the collection's models via the native Array.sort method.
This is an instance property that represents the number of models in the collection.
Set this property if you want a collection's models to be an instance of a class other than the default Model
This property tells resourcerer how to determine whether to make a new request or to take a collection out of the cache. It is an array of strings or functions from which its cache key is calculated. See the cacheKey section for more info.
number
The number of milliseconds to keep all collections of this class in the cache after all client components stop referencing it. Note that this is on a collection class basis and not an instance basis because the latter can introduce race conditions into your application.
boolean | (obj: ResourceConfigObject) => boolean
A boolean or function that accepts a resource configuration object and returns a boolean, telling resourcerer to track this collection's request time and report it via the track
method setup in configuration.
Use this as a shortcut when you don't want to define a custom Model class just because the collection doesn't contain the default id field (which is 'id'
), ie:
// the collection will index its models based on the `name` property instead of the default `id` property
static idAttribute = 'name'
constructor: (models: Array<Record<string, any> | Model>, options: object) => void
The Collection's constructor gets passed any initial models, as well as the options from the executor function. Override this to add some custom logic or instance variables for the collection—just be sure to pass the arguments to its .super()
call, as well:
class MyCollection extends Collection<ModelType> {
constructor(models, options={}) {
super(models, options);
// initializing some variable to be used later
this.categoriesList = [];
}
url({category}) {
return `/todos/${category}`;
}
}
Passing in a Model
option or a comparator
option to an instance's constructor will override the statically defined properties on its constructor. Other path
fields (the ones passed from the executor function options property) are passed to the url
as shown in the example above.
add: (models: Record<string, any> | Model | Array<Record<string, any> | Model>, options: Object) => this
Add a new entry or list of entries into the collection. Each entry can be an object of data or a Model instance. Will trigger an update in all subscribed components unless the trigger: true
option is passed. You can also pass a parse: true
option to run the model through its parse method before setting its properties. If an entry already exists on the collection, the new properties will get merged into its existing model.
create: (model: Record<string, any> | Model, options: Object) => Promise<[Model, Response]>
Adds a new entry to the collection and persists it to the server. This is literally the equivalent to calling collection.add()
and then model.save()
. Because it also instantiates the new model, be sure to pass any path params you need in your url as the options argument (the same options in the resource config object). The returned Promise is the same as is returned from Model#save. If the request errors, the model is auto-removed from the collection. Pass the wait: true
option to wait to add the new model until after the save request returns. Subscribed components will update when the new entry is added as well as when the request returns.
All .create() calls must have a .catch attached, even if the rejection is swallowed. Omitting one risks an uncaught Promise rejection exception if the request fails.
fetch: (options: object) => Promise<[this, Response]>
This is the method that resourcerer
uses internally to get server data and set its parsed response as models on the collection. This should rarely need to be used in your application. Subscribed components will update when the request returns.
All .fetch() calls must have a .catch attached, even if the rejection is swallowed. Omitting one risks an uncaught Promise rejection exception if the request fails.
get: (identifier: string | number) => Model | undefined
Collections index their Model instances by either the Model's idAttribute
or, equivalently as a shortcut, by the collection's own static modelIdAttribute
property. The .get()
method takes an id value and returns the quick-lookup model instance if one exists.
has: (identifier: string |number | Model | object) => boolean
Returns whether or not a model exists in a collection. You can pass the model instance itself, a model's data, or a model's id.
parse: (response: any) => Array<Object>
This method takes in the raw server data response and should return the data in the form that should be set on the Collection. It defaults to the identity function, which might suffice for many endpoints. Override this for your custom needs. For example, for some search results with some metadata (in an API that returns a JSON object), we want to set the results as the collection:
parse(response) {
this.totalResults = response.totalResults;
this.pageNumber = response.pageNumber;
this.resultsPerPage = response.resultsPerPage;
return response.results;
}
remove: (models: Record<string, any> | Model | Array<Record<string, any> | Model>, options: Object) => this
Use this to remove a model or models from the collection, which should not often be needed. You can pass in anything or a list of anything that can be accepted via .get(). Pass in silent: true
for subscribed components not to get rerendered.
reset: (models: Array<Record<string, any> | Model>, options: Object) => this
Removes all models and their references from a collection and replaces them with the models passed in. Pass in silent: true
for subscribed components not to get rerendered, and parse: true
to have data get parsed before being set on their respective models.
set: (models: Record<string, any> | Model | Array<Record<string, any> | Model>, options: Object) => this
This is the method that many other write methods (add
, remove
, save
, reset
, etc) use under the hood, and it should rarely if ever need to be used directly in your application. Sets new data as models and merges existing data with their models, and sorts as necessary. Pass in silent: true
for subscribed components not to get rerendered, and parse: true
to have data get parsed before being set on their respective models.
This is just a proxy for the sync module. Its behavior shouldn't be overridden, but it may be useful to wrap it for custom behavior, ie:
Collection.sync = Model.sync = function(model, options) {
// custom logic...
// defer again to the sync module
return sync(this, options);
}
toJSON: () => ModelType[]
Returns each model's data objects in a new array.
at: (index: number) => Model
Returns the model at a given index in the collection. Index can be negative to count backwards from the end.
filter: (predicate: (Model) => boolean) Model[]
Same signature as Array.prototype.filter across a collection's models.
find: (predicate: (Model) => boolean) => Model | undefined
Same signature as Array.prototype.find across a collection's models.
findWhere: (attrs: Partial<ModelType>) => Model | undefined
Returns the model matching the attributes passed in, or undefined if no match is found. Like .find
but a shorthand that uses matching attribute values instead of a predicate function.
map: (predicate: (Model) => any) => any[]
Same signature as Array.prototype.map across a collection's models.
pluck: (attribute: string) => any[]
Returns a list of the specified attribute value for all models.
slice: (startIndex: number[, endIndex: number]) => Model[]
Same signature as Array.prototype.slice across a collection's models.
where: (attrs: Partial<ModelType>) => Model[]
Returns a list of models matching the data values passed in. Like .filter
but a shorthand that uses matching data values instead of a predicate function.