CollectionProperty
Extends:
CollectionProperty
provides a standard means for accessing remote data and was inspired by
Backbone collections. The protocol for interacting with
the data source is delegated to an endpoint so the same application logic can work with data from
a RESTful api, graphql, local test data, or even an in-browser database like localforage. F.lux
ships with support for two endpoints, RestEndpointProperty and PojoEndpointProperty.
F.lux ships with a example using collections in a todo application utilizing an in memory data source. The example uses a local data source to make setup dead simple while still demonstrating the basic features of creating and interacting with collections.
Basic operations
add(state, mergeOp)
all()
clear()</li> <li>
create(model)</li> <li>
destroy(id)</li> <li>
fetch(filter, mergeOp)</li> <li>
find(id)</li> <li>
get(id)</li> <li>
has(id)</li> <li>
remove(id)`
Utility functions
entries()
every(iteratee, context)
filter(iteratee, context)
groupBy(callback, context)
keys()
map(iteratee, context)
reduce(iteratee, acc, context)
some(iteratee, context)
sortBy(...iteratee)
values()
Model access
Properties managed by a collection receive an f.lux accessor ($()
) with additional
capabilities related to the collection. The accessor class is $ShadowModelAccess.
collection()
- gets the Collection managing this modeldestroy()
- permanently deletes the model from the collection using CollectionProperty#destroyid()
- gets the ID used by the data source for tracking the modelisWaiting()
- is a network operation in progress associated with this modelisDirty()
- has the model been modified since it was last saved/retrievedisNew()
- gets whether the model has yet to be written to the collection's endpointremove()
- removes the model from the collection using CollectionProperty#removesave()
- save the model using CollectionProperty#save
Paging
The collection provides redimentary paging support for potentially large collections. The
current implementation simply grows the collection size wtih each call to fetchNext()
and does not make any efforts to remove previous models. (A likely future enhancement)
fetchNext()
- gets the next group of modelsisPaging()
- gets if a paging request is outstanding (only one paging request per collection allowed at one time)hasMorePages()
- does the endpoint have additional modelsnextOffset()
- gets the offset for the next paging requestresetPaging()
- resets the internal paging variablessetLimit()
- change the number of models requested with eachfetchNext()
request
Endpoints
Collections represent a protocol independent means of managing persistent models that exist outside the application state. Endpoints implement the protocol connection to the data source. F.lux endpoints have been implemented for RESTful server apis, in-memory, GraphQL, Sqlite, and Couchbase. F.lux ships with support for RESTful servers and in-memory.
A simple, explicit example of creating a collection and assigning an endpoint:
const rootProperty = store.root();
const collection = new CollectionProperty(colType);
const ep = new RestEndpointProperty.createFor("http://some-url.com/an-api");
collection.setEndpoint(ep);
root._keyed.addProperty("aCollection", collection);
The Todo Collection Example demonstrates a more typical example of setting up a collection.
Query filters
Collection models are retrieved in full using CollectionProperty#fetch that has the following signature:
fetch(filter=null, mergeOp=REPLACE_OPTION, replaceAll=true)
where:
filter
- a query filter object ornull
for no endpoint filteringmergeOp
- one ofDEFAULTS_OPTION
,MERGE_OPTION
, orREPLACE_OPTION
and specifies how to combine an existing model with a matching ID with a newly retrieved model.replaceAll
- a boolean wheretrue
means replace the current colleciton models with the returned models.
The filter
parameter is a specialized object generated by the endpoint method queryBuilder()
.
A query builder is specialized to the endpoint and expose the following methods:
equals(name, value)
gt(name, value)
gte(name, value)
lt(name, value)
lte(name, value)
An example of using a query builder is:
const qb = colleciton.endpoint.queryBuilder();
qb.equals("name", "fred");
collection.fetch(qb);
Errors
Methods utilizing the collection endpoint are asynchronous and return a Promise
. Errors generated
during an endpoint operation reject using an Error
with several specialized properties:
status
- an HTTP status code for the error typeendpointError
- the error object generated by the endpoint
Auto-checkpointing
The Property
class supports checkpointing state that can be reset at a later time using
Property#resetToCheckpoint. Collections support setting an 'auto-checkpoint' flag
that will result in managed models automatically setting a checkpoint on change. This handy
for situations like a 'Cancel' button on a form where all changes need to be undone. The
checkpoints are automatically cleared when a model is saved.
isAutocheckpoint()
setAutocheckpoint(auto)
Middleware
A middleware operation is invoked before each asynchronous/network operation involving the endpoint. Middleware operations are functions with the following format
function middleware(collectionShadow, collectionProperty, op): Promise
Middleware functions must return a Promise
and are invoked in the order registered. A function
generating an error will terminate the middleware chain and the collection operation will not
be performed.
CreateOp
- invoked prior to create rquestsDestroyOp
- invoked prior to destroy rquestsFetchOp
- invoked prior to fetch rquestsFindOp
- invoked prior to find rquestsUpdateOp
- invoked prior to update rquests- `` -
Events
A colleciton is an Event Emitter and generates the following events:
ChangeEvent
- collection changesDeletedEvent
- collection destroy() successFetchedEvent
- collection fetch() successFoundEvent
- collection find() successErrorEvent
- error during an operationSavedEvent
- collection save() success
Events are can be utilized to handle authorization errors, offline support, logging, or debugging tools.
Static Method Summary
Static Public Methods | ||
public static |
createClass(shadowType: Object | CollectionShadow, typeCallback: function(type: StateType), initialState: Object): ObjectProperty Factory function for creating an |
|
public static |
defineType(PropClass: CollectionShadow, ShadowType: Object | CollectionShadow, typeCallback: function(type: StateType), initialState: Object): * Factory function for setting up the StateType |
Constructor Summary
Public Constructor | ||
public |
constructor(stateType: *) |
Member Summary
Public Members | ||
public get |
Gets the endpoint for accessing the remote data source. |
|
public get |
endpointId: string: * Gets the endpoint ID, which for RestEndpointProperty is its URL. |
|
public |
pagingTime: * |
|
public get |
size: * Gets the number of models contained in the collection. |
Method Summary
Public Methods | ||
public |
Synchronously adds a new model object to the collection. |
|
public |
Bulk adds multiple models. |
|
public |
clean(json: *): * |
|
public |
Removes the endpoint from the collection. |
|
public |
Combines an CollectionProperty#add and CollectionProperty#save actions. |
|
public |
Permantently deletes the model with the endpoint and removes it from the collection. |
|
public |
extractId(model: *): * Used by the private _shadow() method to get the id from the model JSON representation as returned by the subclass doXXX() apis. |
|
public |
Fetches all the models from the endpoint. |
|
public |
Fetches the next set of models from the endpoint. |
|
public |
Gets a model by ID. |
|
public |
Gets a model by ID. |
|
public |
this method is experimental.
Gets an object capable of providing a persisted version of this collection. |
|
public |
Gets if the collection contains a matching model. |
|
public |
hasMorePages(state: *): * Gets if additional paging calls will return additional results. |
|
public |
Sets whether auto-checkpointing is enabled. |
|
public |
isConnected(): * Gets if the collection is active (has a shadow) and an endpoint. |
|
public |
isFetching(): * Gets if a fetching operation that will replace ALL models is in progress. |
|
public |
isNew(id: *): * Gets if a model has never been persisted to the endpoint. |
|
public |
isNewModel(shadow: *): * Gets if a model shadow state model represents a model that has never been persisted to the endpoint. |
|
public |
isPaging(state: *): * Gets if a paging operation (CollectionProperty#fetchNext) call is in progress. |
|
public |
|
|
public |
modelEntries(state: *): Array Gets an iterator with [ID, model] paris. |
|
public |
modelKeys(state: *): Iterator Gets an iterator containing each model IDs. |
|
public |
modelKeysArray(state: *): Array Gets an array containing each model iDs. |
|
public |
modelValues(state: *): Iterator Gets an iterator containing each f.lux shadow state model. |
|
public |
modelsArray(state: *): array Gets the shadow models currently managed by the collection. |
|
public |
nextOffset(): * Gets the offset for the next paging request. |
|
public |
remove(id: *) Synchronously removes the model from the collection without performing an endpoint operation. |
|
public |
Removes all models from the collection and marks the collection as having not synched with the endpoint. |
|
public |
Resets all internal paging tracking variables but does not affect currently stored models. |
|
public |
Saves a model through the endpoint. |
|
public |
setAutocheckpoint(auto: boolean) Sets whether auto-checkpointing should be enabled. |
|
public |
setEndpoint(endPoint: *) Sets the CollectionProperty#endpoint. |
|
public |
setIdName(idName: *) Sets the property name containing the model ID. |
|
public |
Sets the number of models to request with each paging request. |
|
public |
Bulk replaces current models with an array of new models. |
|
public |
setOfflineState(offline: Object) this method is experimental.
Sets an object capable of providing a persisted version of this collection. |
|
public |
use(op: *, mw: *) Registers collection middleware operation. |
Inherited Summary
From class Property | ||
public |
|
|
public |
|
|
public |
|
|
public |
[_checkpoint]: {"data": *} |
|
public |
[_impl]: * |
|
public |
|
|
public |
[_mixins]: *[] |
|
public |
[_parent]: * |
|
public |
[_pid]: * |
|
public |
[_readonly]: * |
|
public |
[_shader]: * |
|
public |
[_stateType]: * |
|
public |
[_store]: * |
|
public |
Use this.$$() in shadow methods to get access to the property. |
|
public |
Gets if autoshadowing is enabled for this property. |
|
public |
Copies the current actual state for later reset using Property#resetToCheckpoint. |
|
public |
Clears an existing checkpoint created using Property#checkpoint. |
|
public |
Creates the object to be assigned to the shadow.$ property. |
|
public |
Gets the path from root property using a dot ( |
|
public |
getCheckpoint(): * Gets the checkpoint state previously recorded using Property#checkpoint. |
|
public |
getInitialState(state: *): * Gets the initial state for a property at the beginning of the property mounting process. |
|
public |
Gets if an existing checkpoint has be created using Property#checkpoint. |
|
public |
initialState(): * Gets the result from StateType#computeInitialState. |
|
public |
Gets if the property is currently shadowing an actual state property. |
|
public |
Gets if property is an actual isolated property managed by the store. |
|
public |
Gets if the property allows for assignment through the shadow state, ie |
|
public |
Gets if this is the shadow state root property. |
|
public |
The property name by which this property is referenced by the Property.parent. |
|
public |
nextState(): * Gets what the actual state for this property will be after the Store updates all pending actions. |
|
public |
Gets the object containing or managing this property. |
|
public |
Gets the parent property. |
|
public |
Gets the parent's shadow property. |
|
public |
path(): [] Gets the Property#name components from the root property to this property. |
|
public |
Gets the unique f.lux ID for this property. |
|
public |
propertyChildInvalidated(childProperty: Property, sourceProperty: Property) A child property or one of its descendents wil be changing state. |
|
public |
Invoked by the f.lux shadowing process after a property initially shadows a state property. |
|
public |
Invoked by the f.lux shadowing process after a property is reshadowed. |
|
public |
Invoked by the f.lux shadowing process just before a property initially shadows a state property. |
|
public |
Invoked by the f.lux shadowing process just before a property will be removed from the shadow state. |
|
public |
Replaces the current property state with a checkpoint state previously recorded using Property#checkpoint. |
|
public |
Gets the shadow state root property for the Store managing this property. |
|
public |
rootShadow(): Shadow Gets the root shadow state for the Store managing this property. |
|
public |
setAutoshadow(auto: boolean): * Sets the auto shadow property flag. |
|
public |
setImplementationClass(ImplClass: *) |
|
public |
setInitialState(state: *): Property Explicitly sets an initial state that will be used if the state tree does not have a value for this property. |
|
public |
setReadonly(readonly: *) Sets the readonly flag which will prevent an assignment from changing the value. |
|
public |
setShadowClass(ShadowClass: Shadow) Sets the class to be used for the shadow api |
|
public |
shader(state: *): * Gets the Shader instance for this property. |
|
public |
shadowClass(): * Returns the Shadow subclass used to virtualize the state property. |
|
public |
Gets the path from root property using a slash ( |
|
public |
state(): * Gets the actual state being shadowed. |
|
public |
stateType(): * Gets the StateType used for creating this property. |
|
public |
store(): * Gets the {@Link Store} containing the application state. |
|
public |
touch() Triggers a reshadow of the properties shadow state. |
|
public |
typeName(): * Gets this property's StateType.typeName value. |
|
public |
Makes changes to the next proeprty state. |
Static Public Methods
public static createClass(shadowType: Object | CollectionShadow, typeCallback: function(type: StateType), initialState: Object): ObjectProperty source
Factory function for creating an CollectionProperty
subclass. The generated class will have
the type
StateType descriptor set upon return.
Example usage:
class SomeShadow extends CollectionShadow {
// definition here
}
export default CollectionProperty.createClass(SomeShadow, type => {
// configure type variable
});
Params:
Name | Type | Attribute | Description |
shadowType | Object | CollectionShadow |
|
|
typeCallback | function(type: StateType) |
|
a callback function that will be passed the StateType spec for additional customization, such as setting autoshadow, initial state, or readonly. |
initialState | Object |
|
={} - the initial state for the new property. |
public static defineType(PropClass: CollectionShadow, ShadowType: Object | CollectionShadow, typeCallback: function(type: StateType), initialState: Object): * source
Factory function for setting up the StateType type
class variable with an appropriately
configured intial state.
Example usage:
export default class TodosCollection extends CollectionProperty {
// implement property here
}
class TodosShadow extends CollectionShadow {
// implement shadow api here
}
ObjectProperty.defineType(TodosCollection, TodosShadow, type => {
// configure type variable
});
Params:
Name | Type | Attribute | Description |
PropClass | CollectionShadow |
|
|
ShadowType | Object | CollectionShadow |
|
Shadow` subclass or object literal api definition. If object literal specified, each property and function is mapped onto a Shadow subclass. |
typeCallback | function(type: StateType) |
|
a callback function that will be passed the StateType spec for additional customization, such as setting autoshadow, initial state, or readonly. |
initialState | Object |
|
the initial state for the new property. |
Return:
* |
Public Constructors
public constructor(stateType: *) source
If a StateType is not passed to this constructor then one is located using StateType.from thus ensuring the f.lux shadowing process is defined for this property.
Override:
Property#constructorParams:
Name | Type | Attribute | Description |
stateType | * |
Public Members
public get endpointId: string: * source
Gets the endpoint ID, which for RestEndpointProperty is its URL.
public pagingTime: * source
Public Methods
public addModel(state: object, mergeOp: string): * source
Synchronously adds a new model object to the collection. Call model.$().save()
to persist the newly
added object.
Return:
* | the object's ID. And ID is assigned if the 'id' parameter was not set and it could not
be found in the |
public addModels(models: array, mergeOp: string, syncOp: boolean) source
Bulk adds multiple models. Models must have an ID as it is assumed they have been previously saved.
Params:
Name | Type | Attribute | Description |
models | array | array of model values |
|
mergeOp | string |
|
one of |
syncOp | boolean |
|
sets the |
public clearEndpoint() source
Removes the endpoint from the collection. This has the side-effect of clearing the mdoels.
public create(model: Object): Promise source
Combines an CollectionProperty#add and CollectionProperty#save actions.
Params:
Name | Type | Attribute | Description |
model | Object | the json data |
public destroy(id: *): Promise source
Permantently deletes the model with the endpoint and removes it from the collection.
Params:
Name | Type | Attribute | Description |
id | * | the model ID to delete |
public extractId(model: *): * source
Used by the private _shadow() method to get the id from the model JSON representation as returned by the subclass doXXX() apis. The default implementation simply returns the 'id' model property.
Params:
Name | Type | Attribute | Description |
model | * |
Return:
* |
public fetch(filter: *, mergeOp: string, replaceAll: boolean, callback: *): Promise source
Fetches all the models from the endpoint.
Params:
Name | Type | Attribute | Description |
filter | * |
|
filter object created using the endpoint. |
mergeOp | string |
|
one of |
replaceAll | boolean |
|
set to |
callback | * | invoked before retrieved models are process or in case of an error |
public fetchNext(mergeOp: string): Promise source
Fetches the next set of models from the endpoint. This method differs from
CollectionProperty#fetch by passing offset
and limit
filter criteria to the
endpoint.
Params:
Name | Type | Attribute | Description |
mergeOp | string |
|
one of |
Return:
Promise | resolves with a single argument of an array of model json objects as returned from the endpoint. |
public find(id: *): Promise source
Gets a model by ID. The method looks for a matching model in the collection. If one is not found then one is requested from the endpoint.
Params:
Name | Type | Attribute | Description |
id | * | the model ID |
public getModel(id: *): Object source
Gets a model by ID. The method looks for a matching model in the collection and never looks for one remotely through the endpoint.
Params:
Name | Type | Attribute | Description |
id | * | the model ID |
public getOfflineState(): Object source
Gets an object capable of providing a persisted version of this collection.
public hasModel(id: *): boolean source
Gets if the collection contains a matching model.
Params:
Name | Type | Attribute | Description |
id | * | the model ID |
public hasMorePages(state: *): * source
Gets if additional paging calls will return additional results.
Params:
Name | Type | Attribute | Description |
state | * |
|
Return:
* |
public isConnected(): * source
Gets if the collection is active (has a shadow) and an endpoint.
Return:
* |
public isFetching(): * source
Gets if a fetching operation that will replace ALL models is in progress.
Return:
* |
public isNew(id: *): * source
Gets if a model has never been persisted to the endpoint.
Params:
Name | Type | Attribute | Description |
id | * |
Return:
* |
public isNewModel(shadow: *): * source
Gets if a model shadow state model represents a model that has never been persisted to the endpoint.
Params:
Name | Type | Attribute | Description |
shadow | * |
Return:
* |
public isPaging(state: *): * source
Gets if a paging operation (CollectionProperty#fetchNext) call is in progress.
Params:
Name | Type | Attribute | Description |
state | * |
|
Return:
* |
public modelEntries(state: *): Array source
Gets an iterator with [ID, model] paris.
Params:
Name | Type | Attribute | Description |
state | * |
public modelKeys(state: *): Iterator source
Gets an iterator containing each model IDs.
Params:
Name | Type | Attribute | Description |
state | * |
|
Return:
Iterator |
public modelKeysArray(state: *): Array source
Gets an array containing each model iDs.
Params:
Name | Type | Attribute | Description |
state | * |
public modelValues(state: *): Iterator source
Gets an iterator containing each f.lux shadow state model.
Params:
Name | Type | Attribute | Description |
state | * |
|
Return:
Iterator |
public modelsArray(state: *): array source
Gets the shadow models currently managed by the collection.
Params:
Name | Type | Attribute | Description |
state | * |
Return:
array | all models being managed by the collection |
public remove(id: *) source
Synchronously removes the model from the collection without performing an endpoint operation.
Params:
Name | Type | Attribute | Description |
id | * | the model id or cid |
public removeAllModels() source
Removes all models from the collection and marks the collection as having not synched with the endpoint.
public resetPaging() source
Resets all internal paging tracking variables but does not affect currently stored models.
public save(id: *, mergeOp: string): Promise source
Saves a model through the endpoint.
Params:
Name | Type | Attribute | Description |
id | * | the model id or cid |
|
mergeOp | string |
|
one of |
public setAutocheckpoint(auto: boolean) source
Sets whether auto-checkpointing should be enabled.
Params:
Name | Type | Attribute | Description |
auto | boolean |
|
public setEndpoint(endPoint: *) source
Sets the CollectionProperty#endpoint.
Params:
Name | Type | Attribute | Description |
endPoint | * |
public setIdName(idName: *) source
Sets the property name containing the model ID. Default is id
.
Params:
Name | Type | Attribute | Description |
idName | * |
public setLimit(limit: number) source
Sets the number of models to request with each paging request. The default paging size is 50.
Params:
Name | Type | Attribute | Description |
limit | number |
public setModels(models: array, syncOp: boolean) source
Bulk replaces current models with an array of new models.
Params:
Name | Type | Attribute | Description |
models | array | array of model values |
|
syncOp | boolean |
|
sets the |
public setOfflineState(offline: Object) source
Sets an object capable of providing a persisted version of this collection. The object must minimally expose a single method with the form:
function restore()
Method sets the collection state for offline access. Typically invoked by application logic after
a failed fetch()
to the endpoint.
An object is used as the offline state management entity because it will normally perform other duties such as registering for ChangeEvent to persistently store collection state on changes and support deleting previous backups
Params:
Name | Type | Attribute | Description |
offline | Object | the object containing the |
public use(op: *, mw: *) source
Registers collection middleware operation. A middleware operation is invoked before each asynchronous/ network operation. Middleware operations are functions with the following format:
function mwCallback(collectionShadow, collectionProperty)
Middleware functions must return a promise and are invoked in the order registered. A function generating an error will terminate the middleware chain and the collection operation will not be performed.
Params:
Name | Type | Attribute | Description |
op | * | ||
mw | * |