Collection
Collections are ordered sets of models. You can bind "change"
events to be notified when any model in the collection has been modified, and listen for "add"
and "remove"
events.
Any event that is triggered on a model in a collection will also be triggered on the collection directly, for convenience. This allows you to listen for changes to specific attributes in any model in a collection.
Methodsβ
add()β
collection.add(models, [options])
Add a model (or an array of models) to the collection, firing an "add"
event for each model, and an "update"
event afterwards. This is a variant of set()
with the same options and return value, but it always adds and never removes. If you're adding models to the collection that are already in the collection, they'll be ignored, unless you pass { merge: true }
, in which case their attributes will be merged into the corresponding models, firing any appropriate "change"
events.
const shapes = new mvc.Collection;
shapes.on('add', function(shape) {
console.log(shape.get('name'));
// A
// B
});
shapes.add([
{ name: 'A' },
{ name: 'B' }
]);
Note that adding the same model (a model with the same id
) to a collection more than once is a no-op.
at()β
collection.at(index)
Get a model from a collection, specified by index. Useful if your collection is sorted, and if your collection isn't sorted, at
will still retrieve models in insertion order. When passed a negative index, it will retrieve the model from the back of the collection.
clone()β
collection.clone()
Returns a new instance of the collection with an identical list of models.
comparator()β
collection.comparator
By default there is no comparator for a collection. If you define a comparator, it will be used to sort the collection any time a model is added. A comparator can be defined as a sortBy
(pass a function that takes a single argument), as a sort
(pass a comparator function that expects two arguments), or as a string indicating the attribute to sort by.
"sortBy" comparator functions take a model and return a numeric or string value by which the model should be ordered relative to others. "sort" comparator functions take two models, and return -1
if the first model should come before the second, 0
if they are of the same rank and 1
if the first model should come after. Note that JointJS depends on the arity of your comparator function to determine between the two styles, so be careful if your comparator function is bound.
const Shape = new mvc.Model;
const shapes = new mvc.Collection;
shapes.comparator = 'order';
shapes.add(new Shape({ order: 3, letter: "C" }));
shapes.add(new Shape({ order: 2, letter: "B" }));
shapes.add(new Shape({ order: 1, letter: "A" }));
console.log(shapes.pluck('letter')); // A, B, C
Note: Collections with a comparator will not automatically re-sort if you later change model attributes, so you may wish to call sort
after changing model attributes that would affect the order.
each()β
collection.each(fn, [context])
Iterate over models of a collection, and invoke fn
for each model. fn
is invoked with 3 arguments: (model, index, array).
const a = new mvc.Model({ id: 1, label: 'a' });
const b = new mvc.Model({ id: 2, label: 'b' });
const c = new mvc.Model({ id: 3, label: 'c' });
const col = new mvc.Collection([a, b, c]);
col.each((model, i) => model.set({ customData: i }));
col.each((model) => console.log(model.get('customData')));
// 0
// 1
// 2
extend()β
mvc.Collection.extend(properties, [classProperties])
To create a Collection class of your own, extend mvc.Collection
. Provide instance properties, and optional classProperties to be attached directly to the constructor function.
filter()β
collection.filter(fn, [context])
Iterate over models of a collection, returning an array of all models fn
returns truthy for. fn
is invoked with three arguments: (model, index, array).
const a = new mvc.Model({ id: 3, label: 'a' });
const b = new mvc.Model({ id: 2, label: 'b' });
const c = new mvc.Model({ id: 1, label: 'c' });
const d = new mvc.Model({ id: 0, label: 'd' });
const col = new mvc.Collection([a, b, c, d]);
console.log(col.filter((model) => model.get('id') === 0).length); // 1
find()β
collection.find(fn, [context])
Return the first element in the collection that satisfies the provided testing function. If no values satisfy the testing function, undefined
is returned.
const a = new mvc.Model({ id: 3, label: 'a' });
const b = new mvc.Model({ id: 2, label: 'b' });
const c = new mvc.Model({ id: 1, label: 'c' });
const d = new mvc.Model({ id: 0, label: 'd' });
const col = new mvc.Collection([a, b, c, d]);
console.log(col.find((model) => model.get('label') === 'c').id); // 1
findIndex()β
collection.findIndex(fn, [context])
Return the index of the first element in the collection that satisfies the provided testing function. If no elements satisfy the testing function, -1
is returned.
const a = new mvc.Model({ id: 3, label: 'a' });
const b = new mvc.Model({ id: 2, label: 'b' });
const c = new mvc.Model({ id: 1, label: 'c' });
const d = new mvc.Model({ id: 0, label: 'd' });
const col = new mvc.Collection([a, b, c, d]);
console.log(col.findIndex((model) => model.get('label') === 'c')); // 2
first()β
collection.first()
Return the first model of a collection.
get()β
collection.get(id)
Get a model from a collection, specified by an id
, a cid
, or by passing in a model.
includes()β
collection.includes(value)
Return true
if model is found in a collection.
const a = new mvc.Model({ id: 3, label: 'a' });
const b = new mvc.Model({ id: 2, label: 'b' });
const c = new mvc.Model({ id: 1, label: 'c' });
const d = new mvc.Model({ id: 0, label: 'd' });
const col = new mvc.Collection([a, b, c]);
console.log(col.includes(a)); // true
console.log(col.includes(d)); // false
initialize()β
When creating a Collection, you may choose to pass in the initial array of models. The collection's comparator
may be included as an option. Passing false
as the comparator
option will prevent sorting. If you define an initialize function, it will be invoked when the collection is created. Initialize is an empty function by default. Override it with your own initialization logic.
There are a couple of options that, if provided, are attached to the collection directly: model
and comparator
. Pass null
for models to create an empty Collection with options
.
const shapes = new mvc.Collection(null, {
model: Shape
});
isEmpty()β
collection.isEmpty()
Return true
if a collection is empty.
const col = new mvc.Collection([]);
console.log(col.isEmpty()); // true
col.set([new mvc.Model({ id: 1, label: 'a' })]);
console.log(col.isEmpty()); // false
last()β
collection.last()
Return the last model of a collection.
length()β
collection.length
Like an array, a Collection maintains a length
property, counting the number of models it contains.
map()β
collection.map(fn, [context])
Create an array of values by running each model in the collection through fn
. fn
is invoked with three arguments: (model, index, array).
const a = new mvc.Model({ id: 3, label: 'a' });
const b = new mvc.Model({ id: 2, label: 'b' });
const c = new mvc.Model({ id: 1, label: 'c' });
const d = new mvc.Model({ id: 0, label: 'd' });
const col = new mvc.Collection([a, b, c, d]);
console.log(col.map((model) => model.get('label')).join(' ')); // 'a b c d'
model()β
collection.model([attrs], [options])
Override this property to specify the model class that the collection contains. If defined, you can pass raw attributes objects (and arrays) and options to add()
, and reset()
, and the attributes will be converted into a model of the proper type using the provided options, if any.
const Shapes = mvc.Collection.extend({
model: Shape
});
A collection can also contain polymorphic models by overriding this property with a constructor that returns a model.
const Shapes = mvc.Collection.extend({
model: function(attrs, options) {
if (condition) {
return new ShapeA(attrs, options);
} else {
return new ShapeB(attrs, options);
}
}
});
modelId()β
collection.modelId(attrs, idAttribute)
Override this method to return the value the collection will use to identify a model given its attributes. Useful for combining models from multiple tables with different idAttribute
values into a single collection.
By default returns the value of the given idAttribute
within the attrs
, or failing that, id
. If your collection uses a model factory and the id ranges of those models might collide, you must override this method.
const Shapes = mvc.Collection.extend({
modelId: function(attrs) {
return attrs.type + attrs.id;
}
});
const shapes = new Shapes([
{ type: 'a', id: 1 },
{ type: 'b', id: 1 }
]);
console.log(shapes.get('a1').id); // 1
models()β
collection.models
Raw access to the JavaScript array of models inside of the collection. Usually you'll want to use get()
or at()
to access model objects, but occasionally a direct reference to the array is desired.
pop()β
collection.pop([options])
Remove and return the last model from a collection. Takes the same options as remove()
.
preinitialize()β
For use with collections as ES classes. If you define a preinitialize
method, it will be invoked when the Collection is first created and before any instantiation logic is run for the Collection.
class Shapes extends mvc.Collection {
preinitialize() {
this.on('add', function() {
console.log('Add model event got fired!');
});
}
}
push()β
collection.push(model, [options])
Like add()
, but always adds a model at the end of the collection and never sorts.
reduce()β
collection.reduce(fn, [initialValue])
Reduce a collection to a value which is the accumulated result of running each model in the collection through fn
, where each successive invocation is supplied the return value of the previous. If initialValue
is not given, the first model in the collection is used as the initial value. fn
is invoked with four arguments: (accumulator, currentValue, currentIndex, array).
const collection = new mvc.Collection([new mvc.Model({ id: 1, label: 'a' })]);
console.log(collection.reduce((acc, model) => acc.get('id') + model.id )); // 2
remove()β
collection.remove(models, [options])
Remove a model (or an array of models) from the collection, and return them. Each model can be a Model instance, an id
string or a JS object, any value acceptable as the id
argument of collection.get
. Fires a "remove"
event for each model, and a single "update"
event afterwards, unless { silent: true }
is passed. The model's index before removal is available to listeners as options.index
.
reset()β
collection.reset([models], [options])
Use reset to replace a collection with a new list of models (or attribute hashes), triggering a single "reset"
event on completion, and without triggering any "add"
or "remove"
events on any models. Returns the newly-set models. For convenience, within a "reset"
event, the list of any previous models is available as options.previousModels
. Pass null
for models
to empty your Collection with options
.
Calling collection.reset()
without passing any models as arguments will empty the entire collection.
set()β
collection.set(models, [options])
The set method performs a "smart" update of the collection with the passed list of models. If a model in the list isn't yet in the collection it will be added; if the model is already in the collection its attributes will be merged; and if the collection contains any models that aren't present in the list, they'll be removed. All of the appropriate "add"
, "remove"
, and "change"
events are fired as this happens, with a single "update"
event at the end. Returns the touched models in the collection. If you'd like to customize this behavior, you can change it with options: { add: false }
, { remove: false }
, or { merge: false }
.
If a model
property is defined, you may also pass raw attributes objects and options, and have them be vivified as instances of the model using the provided options. If you set a comparator
, the collection will automatically sort itself and trigger a "sort"
event, unless you pass { sort: false }
or use the { at: index }
option. Pass { at: index }
to splice the model(s) into the collection at the specified index
.
const players = new mvc.Collection([ carlsen, nakamura, caruana, liren ]);
players.set([ carlsen, nakamura, caruana, firouzja ]);
// Fires a "remove" event for "liren", and an "add" event for "firouzja".
// Updates any of "caruana", "nakamura", and carlsen's attributes that may have changed.
shift()β
collection.shift([options])
Remove and return the first model from a collection. Takes the same options as remove()
.
slice()β
collection.slice(begin, end)
Return a shallow copy of this collection's models, using the same options as native Array.prototype.slice.
sort()β
collection.sort([options])
Force a collection to re-sort itself. Note that a collection with a comparator
will sort itself automatically whenever a model is added. To disable sorting when adding a model, pass { sort: false }
to add()
. Calling sort triggers a "sort"
event on the collection.
toJSON()β
collection.toJSON([options])
Return an array containing the attributes hash of each model (via toJSON
) in the collection. This can be used to serialize and persist the collection as a whole.
unshift()β
collection.unshift(model, [options])
Like add()
, but always adds a model at the beginning of the collection and never sorts.