Collections
AJAX Abstraction for Lists of Resources
AJAX Abstraction for Lists of Resources
The model
property is the Model
class that resources should be converted to.
The default implementation looks like this:
import { Model } from 'lore-models';
...
model: Model,
Most of the time, this property won't be needed, except when you need to transform the data for individual resources returned from the server.
For example, let's say you have an API endpoint located at http://localhost:1337/tweets
, that returns a collection of tweets that looks like this:
[
{
id: 1,
text: 'An old tweet'
},
{
id: 2,
text: 'A new tweet'
}
]
If you wanted to retrieve those tweets, you could create this collection:
import { Collection } from 'lore-models';
const TweetCollection = Collection.extend({
urlRoot: 'http://localhost:1337/tweets'
});
const tweets = new TweetCollection();
tweets.fetch();
Once the API call returns, tweet.models
would look like this (exactly mirroring the API response, but converted into Models):
[
new Model({
id: 1,
text: 'An old tweet'
}),
new Model({
id: 2,
text: 'A new tweet'
})
]
And if we converted that into a raw JSON object using tweets.toJSON()
we would see this:
[
{
id: 1,
text: 'An old tweet'
},
{
id: 2,
text: 'A new tweet'
}
]
But sometimes you might want to transform that data, such as changing the name or value of a property, as mentioned in the parse()
docs for Models (link).
For example, let's say we wanted to add a message
field to each model, to resolve a breaking API change. One way to do that would be to account for that in the collection's parse()
method like this:
You can do that by defining a parse()
like this:
import { Collection } from 'lore-models';
const TweetCollection = Collection.extend({
urlRoot: 'http://localhost:1337/tweets',
parse: function(response){
return response.data.map(function(datum){
datum.message = datum.text;
return datum;
});
}
});
const tweets = new TweetCollection();
tweets.fetch();
In the code above, we're iterating through the data provided by the API, and modifying the response to include a message
attribute that mirrors the text
attribute.
Alternatively, we could define that parse method in a custom Tweet
Model like this:
import { Model, Collection } from 'lore-models';
const Tweet = Model.extend({
parse: function(response){
response.message = response.text;
return response;
}
});
const TweetCollection = Collection.extend({
model: Tweet,
urlRoot: 'http://localhost:1337/tweets',
parse: function(response){
return response.data;
}
});
const tweets = new TweetCollection();
tweets.fetch();
In this code we've created a custom Tweet
Model, and defined a parse()
method that knows how to convert a single tweet resource into the format we need. Then, instead of including that logic in the parse()
method for the TweetCollection
, we can leave it out.
By defining the model
for the TweetCollection
, the resources will automatically be cast to a Tweet
, and once the API call returns tweets.models
will be composed like this:
[
new Tweet({
id: 1,
text: 'An old tweet'
}, { parse: true }),
new Tweet({
id: 2,
text: 'A new tweet'
}, { parse: true })
]
And calling tweets.toJSON()
would provide this:
[
{
id: 1,
text: 'An old tweet',
message: 'An old tweet'
},
{
id: 2,
text: 'A new tweet',
message: 'A new tweet'
}
]