keet
Version:
Minimalist view layer for the web
134 lines (118 loc) • 3.58 kB
JavaScript
import { minId } from '../../utils'
/**
* @module keet/CreateModel
* @example
* import { CreateModel } from 'keet'
*
* class myModel extends CreateModel {
* contructor() {
* super()
* // props
* }
* // new extended method
* myMethod(...args){
* this.list = args
* }
* }
*
* const MyModel = new myModel()
*/
// check two objects properties attribute kdata-id and return the value equality
const notEqual = function (a, b) {
return a['kdata-id'] !== b['kdata-id']
}
let async = {}
// We otimize component lifeCycle triggering by trottling the model batch updates
const inform = function (...args) {
if (async[this.mId]) clearTimeout(async[this.mId])
async[this.mId] = setTimeout(() =>
this.exec && typeof this.exec === 'function' && this.exec.apply(null, args)
, 0)
}
/**
* The model constructor, use with template literal having
* ```{{model:<myModel>}}<myModelTemplateString>{{/model:<myModel>}}```
* @alias module:keet/createModel
* @param {*} enableFiltering - any truthy value
*
*/
export default class CreateModel {
constructor (enableFiltering) {
this.mId = CreateModel.genIdentity
async[this.mId] = null
// if enableFiltering is assigned a value, model generation will
// use `listFilter` instead of `list`
this.enableFiltering = enableFiltering || null
this.model = []
// Register callback listener of any changes
Object.defineProperty(this, 'list', {
enumerable: false,
configurable: true,
get: function () {
return this.model
},
set: function (val) {
this.model = val
this.dirty = true
inform.call(this, this.model, this.listFilter)
}
})
// Register callback listener of any changes with filter
Object.defineProperty(this, 'listFilter', {
enumerable: false,
configurable: true,
get: function () {
return !this.prop ? this.model : this.model.filter(obj => obj[this.prop] === this.value)
}
})
}
// set identity for this model
static get genIdentity () {
return minId()
}
/**
* Subscribe to the model changes, the function callback first argument
* is the ```model.list``` and the second argument is ```model.listFilter```
* @param {Function} fn - the function callback for the subscribe
*/
subscribe (fn) {
this.exec = fn
}
/**
* Add new object to the model list
* @param {Object} obj - new object to add into the model list
*/
add (obj) {
this.list = this.list.concat({ ...obj, 'kdata-id': minId() })
}
/**
* Update existing object in the model list
* @param {Object} updateObj - the updated properties
*/
update (updateObj) {
this.list = this.list.map(obj =>
notEqual(obj, updateObj) ? obj : updateObj
)
}
/**
* Filter the model data by selected properties, constructor
* instantiation should be apply with boolean true as argument
* to enable filtering
* @param {string} prop - property of the object
* @param {Object|string|number|Boolean} value - property value
*/
filter (prop, value) {
this.prop = prop
this.value = value
this.list = this.list
}
/**
* Removed existing object in the model list
* @param {Object} destroyObj - the object ref to remove from the model
*/
destroy (destroyObj) {
this.list = this.list.filter(obj => {
return notEqual(obj, destroyObj)
})
}
}