The Model class is a helper for working with data associated to a DataService.
Properties on the Model should use the @attr
decorator for specifying fields specific to the Model's own data. It is these values which will be sent to/from the API via the DataService when the Model is instantiated or saved.
Since the DataService is tied to Redux, and data in Redux must be immutable, this class is immutable. However, it will use a magic setter on each decorated field which will dispatch a Redux action to the DataService's reducer. When the reducer receives the value for the new field, a new instance of the Model will be stored and the current Model instance will be marked for destruction. Thus, we preserve the nature of an immutable architecture, with the convenience of a traditional MVC framework.
Use this decorator to specify which properties on the model are a part of the model's own data, which will be sent to/from the API. It takes a FieldType
, from which we can determine the property's default value, default validation rules and how to render it dynamically. You may optionally provide a second parameter, to specify a different default value for the property being decorated. To set additional validation rules for the property, use the @validation
decorator or one of its variants, such as @required
.
Use this decorator to specify additional validation rules on the property being decorated. Should be used in conjunction with @attr
. The format of the object passed into the decorator should match the validation rules for Validate.JS.
Use this decorator as a convenience for setting a validation rule to specify that a property is required.
Use this decorator to specify a relationship to another Model such that this Model has one of the related Model. For example:
@belongsTo()
organization: IOrganization;
The above example will use the property name to identify the name of the related field's service (which can be specified as the first parameter). It will use a standard naming convention to identify the name of the field on this Model for identifying the ID of the related model to load, in this case it would look for a field named "organizationId" to load the related IOrganization from the "organization" DataService. The relatedFieldName can be specified as the second parameter.
The DataService will return an Observable which will provide new copies of the related Model every time it is updated. If the related Model has not been loaded yet, the DataService will load it and return a "shadow" object while it is loading.
Use this decorator to specify a relationship to another Model such that this Model has many of the related Model. It behaves the exact same as the @belongsTo
decorator, except it assumes the relatedFieldName is pluralized and it returns arrays of the related Model instead.
T : IModelData
Model
- IModel<
T
>
- dateDeleted
- dateUpdated
- fields
- id
- meta
- modelData
- parentIdFieldName
- parentServiceName
- relatedModels
- relationships
- serializeThroughParent
- serviceName
- validationRules
- applyUpdates
- checkFieldUpdateIsAllowed
- delete
- forceReload
- getField
- getFieldError
- getRelated
- getServiceForRelationship
- getValidationRulesForField
- getWillDestroyObservable$
- initializeNewModel
- isFieldDirty
- markForDestruction
- original
- parseFieldValue
- reset
- save
- saveModel
- saveRelatedModels
- setField
- setMetaField
- setRelated
- triggerWillDestroyObservable
- unload
- validate
- validateField
⊕ new Model(modelData: * Partial
<T
> & object
*, meta?: Partial
<IModelMeta<T
>>, relatedModels?: IModelsMap): Model
Defined in Model/Model.ts:105
Parameters:
Name | Type | Default value |
---|---|---|
modelData | Partial <T > & object |
- |
Default value meta |
Partial <IModelMeta<T >> |
{} |
Default value relatedModels |
IModelsMap | {} |
Returns: Model
● dateDeleted: Date
Implementation of IModel.dateDeleted
Defined in Model/Model.ts:84
● dateUpdated: Date
Implementation of IModel.dateUpdated
Defined in Model/Model.ts:81
● fields: IModelKeys< T
& any
, IFieldType<any
>>
Implementation of IModel.fields
Defined in Model/Model.ts:73
● id: string
Defined in Model/Model.ts:78
● meta: IModelMeta<T
>
Defined in Model/Model.ts:104
● modelData: Partial
<T
>
Defined in Model/Model.ts:103
● parentIdFieldName: string
Implementation of IModel.parentIdFieldName
Defined in Model/Model.ts:93
● parentServiceName: any
Implementation of IModel.parentServiceName
Defined in Model/Model.ts:90
● relatedModels: IModelsMap
Defined in Model/Model.ts:105
● relationships: object
Implementation of IModel.relationships
Defined in Model/Model.ts:75
● serializeThroughParent: boolean
Implementation of IModel.serializeThroughParent
Defined in Model/Model.ts:87
● serviceName: string
Implementation of IModel.serviceName
Defined in Model/Model.ts:72
● validationRules: IModelKeys<T
>
Implementation of IModel.validationRules
Defined in Model/Model.ts:74
geterrors(): object
seterrors(value: object
): void
Defined in Model/Model.ts:664
Get the list of errors, which may have been created from calling this.validate()
or as a response from the API.
Returns: object
Defined in Model/Model.ts:673
Dispatch an action to Redux to set the error state of the Model.
Parameters:
Name | Type | Description |
---|---|---|
value | object |
Returns: void
gethasUnsavedChanges(): boolean
Defined in Model/Model.ts:704
Determine if the model or its previously loaded relationships have unsaved changes.
Returns: boolean
getisDestroying(): boolean
Defined in Model/Model.ts:591
Determine if the current instance of the Model has been marked for destruction. That is, this instance is being removed from the Redux store and its subscriptions are being torn down.
Returns: boolean
getisDirty(): boolean
Defined in Model/Model.ts:682
Determine if the Model's data has changed without being saved.
Returns: boolean
getisLoading(): boolean
setisLoading(value: boolean
): void
Defined in Model/Model.ts:635
Determine if the Model is currently loading.
Returns: boolean
Defined in Model/Model.ts:644
Dispatch an action to Redux to set the isLoading state of the Model
Parameters:
Name | Type | Description |
---|---|---|
value | boolean |
Returns: void
getisNew(): boolean
Defined in Model/Model.ts:715
Determine if the Model is a new object which has not been committed to the API yet.
Returns: boolean
getisShadow(): boolean
Defined in Model/Model.ts:654
Determine if the Model is a "shadow" object: its data is currently being loaded and this instance of the Model is used as a temporary placeholder until we get a response from the API.
Returns: boolean
getparentModelId(): any
setparentModelId(value: any
): void
Defined in Model/Model.ts:95
Returns: any
Defined in Model/Model.ts:99
Parameters:
Name | Type |
---|---|
value | any |
Returns: void
▸ applyUpdates(changes?: Partial
<T
>, meta?: Partial
<IModelMeta<T
>>, relatedModels?: any
): IModel<T
>
Implementation of IModel.applyUpdates
Defined in Model/Model.ts:351
Since this class is meant to be immutable, you can apply new updates here. The changes will be deep merged with the existing modelData and/or meta, and a new instance of the class will be returned with those values without mutating the current instance of the class.
Note that this is applied locally. Chances are you will want to dispatch an action instead, via one of the magic setters (so your components will know to update).
Parameters:
Name | Type | Default value |
---|---|---|
Default value changes |
Partial <T > |
{} |
Default value meta |
Partial <IModelMeta<T >> |
{} |
Default value relatedModels |
any |
{} |
Returns: IModel<T
>
▸ checkFieldUpdateIsAllowed(key: any
, value: any
): void
Defined in Model/Model.ts:408
Throw a TypeError if the provided key is an invalid fieldType, or the value is an invalid type for that fieldType.
Parameters:
Name | Type | Description |
---|---|---|
key | any |
- |
value | any |
Returns: void
▸ delete(): Promise
<IModel<T
>>
Defined in Model/Model.ts:286
Dispatch an action to Redux to delete the Model
Returns: Promise
<IModel<T
>>
▸ forceReload(): void
Implementation of IModel.forceReload
Defined in Model/Model.ts:334
Dispatch an action to the DataService to force it to reload the model from the API.
Returns: void
▸ getField(fieldName: string
, defaultValue?: any
): any
Defined in Model/Model.ts:391
This method is called by the magic getters for the properties decorated by the @attr decorator. The actual data for the decorated properties is stored in modelData.
Parameters:
Name | Type | Description |
---|---|---|
fieldName | string |
- |
Optional defaultValue |
any |
- |
Returns: any
▸ getFieldError(fieldName: any
): any
Defined in Model/Model.ts:726
Parameters:
Name | Type |
---|---|
fieldName | any |
Returns: any
▸ getRelated(fieldName: string
): any
Defined in Model/Model.ts:450
This method is called by the magic getters for the properties decorated by the @belongsTo and @hasMany decorators.
It will use the relationship definition created by the decorator to grab the DataService of the related field and return an Observable which provides the corresponding item or items.
If the content has not been loaded yet, the DataService will dispatch an action to load the data.
Parameters:
Name | Type | Description |
---|---|---|
fieldName | string |
- |
Returns: any
▸ getServiceForRelationship(relationshipKey: string
): DataService<any
>
Implementation of IModel.getServiceForRelationship
Defined in Model/Model.ts:551
Get the DataService associated to the relationship specified at the given name of the related field
Parameters:
Name | Type | Description |
---|---|---|
relationshipKey | string |
- |
Returns: DataService<any
>
▸ getValidationRulesForField(fieldName: any
): any
Defined in Model/Model.ts:275
Get the validationRules for the given fieldName. Works with local or nested fields.
Parameters:
Name | Type | Description |
---|---|---|
fieldName | any |
- |
Returns: any
▸ getWillDestroyObservable$(): Observable
<boolean
>
Defined in Model/Model.ts:601
Subscribe to this Observable to be notified when the current instance of the Model has been marked for destruction. That is, this instance is being removed from the Redux store and its subscriptions are being torn down.
Returns: Observable
<boolean
>
▸ initializeNewModel(): void
Implementation of IModel.initializeNewModel
Defined in Model/Model.ts:379
This is a useful hook for doing model-specific initialization when creating a new, unsaved model, such as creating related Models and setting default session values.
Returns: void
▸ isFieldDirty(fieldName: * keyof T
| string
*): boolean
Implementation of IModel.isFieldDirty
Defined in Model/Model.ts:691
Determine if a specific model field of the Model's data has changed without being saved.
Parameters:
Name | Type |
---|---|
fieldName | keyof T | string |
Returns: boolean
▸ markForDestruction(): void
Implementation of IModel.markForDestruction
Defined in Model/Model.ts:575
Call this method just before this Model instance will be removed from the Redux store. This allows us to cleanly unsubscribe to any relationship Observables that were previously subscribed to, in order to avoid a possible memory leak.
Returns: void
▸ original(): this
Implementation of IModel.original
Defined in Model/Model.ts:720
Create a clone of the model without any of the unsaved changes
Returns: this
▸ parseFieldValue(fieldName: string
, value: any
): Promise
<any
>
Implementation of IModel.parseFieldValue
Defined in Model/Model.ts:739
Given a fieldName as a deep path (such as "firstName" or "person.firstName"), this will use that field's own IFieldType.normalize function to parse the given value.
Parameters:
Name | Type |
---|---|
fieldName | string |
value | any |
Returns: Promise
<any
>
▸ reset(): void
Implementation of IModel.reset
Defined in Model/Model.ts:306
Dispatch an action to Redux to reset the Model to its original state. Note: new items will be removed from the Redux store.
Returns: void
▸ save(progressSubscriber?: Subscriber
<any
>): Promise
<IModel<T
>>
Defined in Model/Model.ts:129
Dispatch an action to Redux to commit the pending changes to the API.
Returns a promise which resolves with the new Model on success, or the error response on failure. If there were no changes, it will resolve immediately with the current instance of the Model.
Will reject with validation errors if model is invalid.
Parameters:
Name | Type |
---|---|
Optional progressSubscriber |
Subscriber <any > |
Returns: Promise
<IModel<T
>>
▸ saveModel(progressSubscriber?: Subscriber
<any
>): Promise
<IModel<any
>>
Implementation of IModel.saveModel
Defined in Model/Model.ts:158
Dispatch an action to Redux to commit the pending changes to the API for just this model, without first saving any related models with pending changes (unless they're serialized with this model).
Returns a promise which resolves with the new Model on success, or the error response on failure.
If this model was loaded initially as a nested model, and the parent is marked to serialize this model, then saving this model will instead save the parent model.
Note that this method does not validate the model or check if it has pending changes. You probably want to use the save()
method instead.
Parameters:
Name | Type |
---|---|
Optional progressSubscriber |
Subscriber <any > |
Returns: Promise
<IModel<any
>>
▸ saveRelatedModels(): Promise
<IModel<T
>[]>
Implementation of IModel.saveRelatedModels
Defined in Model/Model.ts:195
Dispatch an action to Redux to commit the pending changes to the API for any of the related models which have already been loaded and would not be serialized when this model is saved. After each model is saved, its new copy is set onto a new copy this model.
Returns a promise which resolves with each of the new models.
Note that this method does not validate the related models before it saves them.
Returns: Promise
<IModel<T
>[]>
▸ setField(fieldName: string
, value: any
): void
Defined in Model/Model.ts:430
This method is called by the magic setters for the properties decorated by the @attr decorator.
Since this class is meant to be immutable, attempting to set on a property will actually dispatch an action to Redux, where a new instance of the Model will be created and stored.
The current instance of the Model will not be mutated!
Parameters:
Name | Type | Description |
---|---|---|
fieldName | string |
- |
value | any |
Returns: void
▸ setMetaField(fieldName: any
, value: any
): void
Defined in Model/Model.ts:621
This method is called by the magic setters for some of the meta properties.
Since this class is meant to be immutable, attempting to set on a property will actually dispatch an action to Redux, where a new instance of the Model will be created and stored.
Parameters:
Name | Type | Description |
---|---|---|
fieldName | any |
- |
value | any |
Returns: void
▸ setRelated(fieldName: string
, value: any
): void
Defined in Model/Model.ts:521
This method is called by the magic setters for the properties decorated by the @belongsTo and @hasMany decorators.
Since the class is meant to be immutable, the related item or items will not be set directly on this instance. Instead, the magic setter for the related field on this class (which tracks the relationship) will be called with the ID or IDs of the value provided, which will dispatch an action to the DataService.
Parameters:
Name | Type | Description |
---|---|---|
fieldName | string |
- |
value | any |
Returns: void
▸ triggerWillDestroyObservable(): void
Defined in Model/Model.ts:564
This is an internal method which will tell the WillDestroyObservable to emit a value
Returns: void
▸ unload(): void
Implementation of IModel.unload
Defined in Model/Model.ts:323
Dispatch an action to Redux to remove this Model from its data store.
Returns: void
▸ validate(includeRelatedModels?: boolean
): IModelKeys<T
>
Defined in Model/Model.ts:221
Perform client-side validation on the Model based on the validationRules as defined by property decorators. The validation results will be returned immediately and dispatched to Redux.
We currently use Validate.JS as our validation library.
If includeRelatedModels
is set to true, any related model on this model which has been loaded previously will be validated as well. The keys for the validation results of nested models will be flattened with "." separator
Parameters:
Name | Type | Default value | Description |
---|---|---|---|
Default value includeRelatedModels |
boolean |
false | - |
Returns: IModelKeys<T
>
▸ validateField(fieldName: any
): any
Defined in Model/Model.ts:251
Perform client-side validation on the Model based on the validationRules as defined for the given fieldName
. The field's validation results will be returned immediately and dispatched to Redux.
Note: this works with nested paths (such as "person.firstName") in addition to fields local to the model.
Parameters:
Name | Type | Description |
---|---|---|
fieldName | any |
- |
Returns: any