@uu-cdh/backbone-collection-transformers
Filtering and mapping for collections, with automatic synchronization.
Rationale | Quickstart | Compatibility | Reference | Planned | Support | Development | BSD 3-Clause
Rationale
Backbone.Collection
has map
and filter
methods, but these methods just return arrays. Would it not be nice if we could have map
and filter
operations that produce new collections, and those new collections would also automatically stay in sync with the input collection? That is what we thought, and that is what this package provides.
One may sometimes want to take a custom collection class and then add the ability to filter or map over another collection. For this reason, we do not provide a single FilteredCollection
class and a single MappedCollection
class, but the functions deriveFiltered
and deriveMapped
, which let you extend any arbitrary collection class with these abilities.
Just like with the familiar map
and filter
functions, there are many situations where we may want to stack multiple transformations on top of each other. This is transparently supported. All mapped and filtered collections have an underlying
property, which lets you directly access the source collection even under many layers of transformation.
Mapping and filtering are just two of many conceivable transformations. If you need to implement a new collection transformer, you can tap into the same transparency by mixing our ProxyMixin
into your transformer class.
Quickstart
We recommend a workflow in which you install dependencies from npm and bundle them with a tool such as Rollup.
// could also use yarn, pnpm, etcetera
npm add @uu-cdh/backbone-collection-transformers
You can also use the library directly from a browser embed, but you may need to set up import maps in that case.
import { Collection } from 'backbone';
import { deriveFiltered, deriveMapped } from '@uu-cdh/backbone-collection-transformers';
var chineseActors = new Collection([{
id: 1,
familyName: 'Gong',
givenName: 'Li',
}, {
id: 2,
givenName: 'Lianjie',
}, {
id: 3,
familyName: 'Ge',
givenName: 'You'
}, {
id: 4,
familyName: 'Zhang',
}, {
id: 5,
givenName: 'Minzhi',
}]);
var FilteredCollection = deriveFiltered();
function hasFullName(actor) {
return !!(actor.get('givenName') && actor.get('familyName'));
}
var fullyNamedActors = new FilteredCollection(chineseActors, hasFullName);
var MappedCollection = deriveMapped();
function joinName(actor) {
var {familyName, givenName, ...otherAttributes} = actor.attributes;
var fullName = `${familyName} ${givenName}`;
return {fullName, ...otherAttributes};
}
var joinedNameActors = new MappedCollection(fullyNamedActors, joinName);
joinedNameActors.toJSON();
chineseActors.set({id: 2, familyName: 'Li'});
chineseActors.remove(3);
chineseActors.set({id: 1, givenName: 'Mei'});
joinedNameActors.underlying;
Compatibility
We jumped some burning hoops to ensure that deriveFiltered
and deriveMapped
can operate both on classic Collection.extend
classes and modern class
classes. Conversely, both types of classes can extend from the classes produced by deriveFiltered
and deriveMapped
. This was less trivial than one might expect, and we had to sacrifice some backwards compatibility with older JavaScript engines in order to make it possible.
That being said, we tried our best to contain the damage. Only syntax and standard APIs are used that have been widely supported at least since May 2016. Unless you target an engine older than that (such as Internet Explorer 11), no transpilation or polyfilling should be required.
Reference
Planned features
We do not have any concrete plans to add any particular other type of collection transformer. That being said, we can easily think of many totally reasonable transformations. For example grouping, sampling, partitioning or chunking. How about zipping, interleaving, intersecting or diffing multiple collections into one? Or even collapsing an entire collection into a single model with reduce or min/max? Or the other way round: exploding a single model into a collection of key/value pairs? If you find a need for a transformation other than mapping or filtering, please let us know and feel welcome to contribute it yourself.
Support
Please report security issues to cdh@uu.nl. For regular bugs, feature requests or any other feedback, please use our issue tracker.
Development
Please see the CONTRIBUTING for everything related to testing, pull requests, versioning, etcetera.
License
Licensed under the terms of the three-clause BSD license. See LICENSE.