StructureJS

0.15.2

A class based utility library for building modular and scalable web platform applications. Features opt-in classes and utilities which provide a solid foundation and toolset to build your next project.

File: ts/model/BaseModel.ts

import IBaseModel from '../interface/IBaseModel';
import IBaseModelOptions from '../interface/IBaseModelOptions';
import BaseObject from '../BaseObject';
import Util from '../util/Util';
/**
 * Base Model is a design pattern used to transfer data between software application subsystems.
 *
 * Note: If the data doesn't match the property names you can set the value manually after update super method has been called.
 * Also in the class you inherit BaseModel from you can override the update method to handle the data how you want.
 *
 * @class BaseModel
 * @extends BaseObject
 * @param [data] {any} Provide a way to update the base model upon initialization.
 * @param [opts] {{ expand:boolean }} Options for the base model.
 * @module StructureJS
 * @submodule model
 * @requires Extend
 * @requires BaseObject
 * @requires Util
 * @constructor
 * @author Robert S. (www.codeBelt.com)
 * @example
 * // Example how to extend the BaseModel class.
 * let data = {
 * make: 'Tesla',
 * model: 'Model S',
 * YeAr: 2014,
 * feature: {
 * abs: true,
 * airbags: true
 * }
 * }
 * let carModel = new CarModel(data);
 *
 *
 * // Example how to extend the BaseModel class.
 * class CarModel extends BaseModel {
 *
 * // You need to have properties so the data will get assigned.
 * // If not the data will not get assigned to the model.
 * make = null;
 * model = null;
 * year = null;
 * allWheel = false; // Set a default value
 *
 * // You can assign BaseModel to a property which will
 * // automatically created it and pass the data to it.
 * feature = FeatureModel
 *
 * // If you have an array of data and want them assign to a BaseModel.
 * feature = [FeatureModel];
 *
 * constructor(data = {}, opts = {}) {
 * super(opts);
 *
 * if (data) {
 * this.update(data);
 * }
 * }
 *
 * // @overridden BaseModel.update
 * update(data) {
 * super.update(data);
 *
 * // If the data doesn't match the property name.
 * // You can set the value(s) manually after the update super method has been called.
 * this.year = data.YeAr;
 * }
 * }
 */
class BaseModel extends BaseObject implements IBaseModel
{
 /**
 * This property helps distinguish a BaseModel from other functions.
 *
 * @property IS_BASE_MODEL
 * @type {boolean}
 * @public
 * @static
 * @readonly
 */
 public static readonly IS_BASE_MODEL:boolean = true;
 /**
 * @property sjsOptions
 * @type {IBaseModelOptions}}
 * @public
 */
 protected sjsOptions:IBaseModelOptions = {
 expand: false,
 };
 constructor(opts:IBaseModelOptions = {})
 {
 super();
 this.sjsOptions.expand = opts.expand === true;
 }
 /**
 * Provide a way to update the Base Model.
 *
 * @method update
 * @param [data={}] {any}
 * @public
 * @example
 * // Example of updating some of the data:
 * carModel.update({ year: 2015, allWheel: true});
 *
 * // Of course you can also do it the following way:
 * carModel.year = 2015;
 * carModel.allWheel = false;
 */
 public update(data:any = {}):any
 {
 Object
 .keys(this)
 .forEach(propertyName =>
 {
 // Ignore the sjsId property because it is set in the BaseObject constructor and we don't want to update it.
 if (propertyName !== 'sjsId')
 {
 const propertyData = this[propertyName];
 const updateData = data[propertyName];
 const dataToUse = (updateData !== void 0) ? updateData : propertyData;
 this._updatePropertyWithDataPassedIn(propertyName, dataToUse);
 }
 });
 return this;
 }
 /**
 * Adds the updateData to the property
 *
 * @method _updatePropertyWithDataPassedIn
 * @param propertyName
 * @param updateData
 * @protected
 */
 protected _updatePropertyWithDataPassedIn(propertyName:any, updateData:any):void
 {
 // If the current property on the model is an array and the updateData is an array.
 if ((this[propertyName] instanceof Array === true) && (updateData instanceof Array === true))
 {
 const isPropertyDataValueAnUninstantiatedBaseModel = (typeof this[propertyName][0] === 'function' && this[propertyName][0].IS_BASE_MODEL === true);
 const isUpdateDataValueAnUninstantiatedBaseModel = (typeof updateData[0] === 'function' && updateData[0].IS_BASE_MODEL === true);
 if (isPropertyDataValueAnUninstantiatedBaseModel === false)
 {
 this[propertyName] = updateData.map(data => this._updateData(null, data));
 }
 else if (isPropertyDataValueAnUninstantiatedBaseModel === true && isUpdateDataValueAnUninstantiatedBaseModel === false)
 {
 // If the property data is an uninstantiated BaseModel then we assume the update data passed in
 // needs to be create as that BaseModel Class.
 const baseModel = this[propertyName][0];
 this[propertyName] = updateData.map(data => this._updateData(baseModel, data));
 }
 else
 {
 this[propertyName] = [];
 }
 }
 else
 {
 this[propertyName] = this._updateData(this[propertyName], updateData);
 }
 }
 /**
 * @method _updateData
 * @param propertyData
 * @param updateData
 * @protected
 */
 protected _updateData(propertyData:any, updateData:any):any
 {
 let returnData:any = null;
 if (this.sjsOptions.expand === false && typeof updateData === 'function' && updateData.IS_BASE_MODEL === true)
 {
 // If updateData is a function and has an IS_BASE_MODEL static property then it must be a child model and we need to return null
 // so it cleans up the BaseModel functions on the property.
 // To create empty model(s) pass { expand: true } for the options.
 return null;
 }
 if (typeof propertyData === 'function' && propertyData.IS_BASE_MODEL === true && updateData)
 {
 // If the propertyData is an instance of a BaseModel class and has not been created yet.
 // Instantiate it and pass in the updateData to the constructor.
 returnData = new propertyData(updateData, this.sjsOptions);
 }
 else if ((propertyData instanceof BaseModel) === true)
 {
 // If propertyData is an instance of a BaseModel class and has already been created.
 // Call the update method and pass in the updateData.
 returnData = propertyData.update(updateData);
 }
 else if ((updateData instanceof BaseModel) === true)
 {
 returnData = updateData.clone();
 }
 else
 {
 // Else just return the updateData to the property.
 returnData = updateData;
 }
 return returnData;
 }
 /**
 * Converts the Base Model data into a JSON object and deletes the sjsId property.
 *
 * @method toJSON
 * @returns {any}
 * @public
 * @example
 * const obj = carModel.toJSON();
 */
 public toJSON():any
 {
 const clone:any = Util.clone(this);
 return Util.deletePropertyFromObject(clone, ['sjsId', 'sjsOptions']);
 }
 /**
 * Converts a Base Model to a JSON string,
 *
 * @method toJSONString
 * @returns {string}
 * @public
 * @example
 * const str = carModel.toJSONString();
 */
 public toJSONString():string
 {
 return JSON.stringify(this.toJSON());
 }
 /**
 * Converts the string json data into an Object and calls the {{#crossLink "BaseModel/update:method"}}{{/crossLink}} method with the converted Object.
 *
 * @method fromJSON
 * @param json {string}
 * @public
 * @example
 * const str = '{"make":"Tesla","model":"Model S","year":2014}'
 * const carModel = new CarModel();
 * carModel.fromJSON(str);
 */
 public fromJSON(json:string):any
 {
 const parsedData:any = JSON.parse(json);
 this.update(parsedData);
 return this;
 }
 /**
 * Create a clone/copy of the Base Model.
 *
 * @method clone
 * @returns {BaseModel}
 * @public
 * @example
 * const clone = carModel.clone();
 */
 public clone():BaseModel
 {
 const clonedBaseModel:BaseModel = new (<any>this).constructor(this);
 return clonedBaseModel;
 }
}
export default BaseModel;
 

AltStyle によって変換されたページ (->オリジナル) /