- +: no depencies
- +: small size, SuperModel.min.js is ~4.5kb uncompressed
- -: only works in environments supporting Proxy
you can install from npm: npm install --save super-model-js
SuperModel( data = {}, emitter = SuperModel.emitter(), store = new Map() )- create a new model.on(type, func),.once(type, func)- model event listener.on[type](func),.once[type](func)- event listener, type as function property.emit(type, ...values)- emit an event with values.emit[type](...values)- emit, event type as a function property.emitAsync(type, ...values)- emit an event with values (non-blocking).del(key)- delete model propertymodel(key, =val)- shorthand function based property get/setmodel({...props})- update properties with an objectmodel[prop]- get/set model propertymodel.async[prop]- get/set model property using promisesmodel.valid(key, =validator)- make a property validate-able by adding a validator func/RegExpmodel.valid[prop]- set - prop validator func/RegExp, get - run validator and get bool result.sync(obj, key, modelProperty = key)- set and update a model property on an object.sync.stop(obj, key)- stop syncing a model property on an object.store()- Map containing all model properties.toJSON()- Get all model.store properties as JSON.toJSONArray()- Get all model.store properties as "[[key, val], ...]".has(key)- checks whether model.store has a certain key.emitter()- just the event emitting part of the model
// view.jsconstmodel=SuperModel()feed.render(awaitmodel.async.news)// news.jsmodel.news=await(awaitfetch('/latest')).json()// psst... it also works if you simply assign a promise as ismodel.news=(awaitfetch('/latest')).json()<textareaid=txtarea>type something...</textarea><articleid=txtdisplay></article>constinput=document.querySelector('#txtarea')constoutput=document.querySelector('#txtdisplay')constmodel=SuperModel()model.sync.msg(input)model.sync.msg(output,'innerText')constmodel=SuperModel()model.valid.username=/^[a-zA-Z0-9._]{3,55}$/gmodel.username='**Bad Username**'model.valid.username// -> falsemodel.valid('username')// -> falsemodel.ui={...someUIcomponent}model.valid.ui=ui=>!ui.hidden&&ui.userlist.includes(model.username)// ormodel.valid('ui',ui=>!ui.hidden&&ui.userlist.includes(model.username))model.valid.ui// -> bool// listen for validation eventmodel.on('validate:username',isValid=>{// ...})// ormodel.on.validate((propName,isValid)=>{if(propName==='username'){// ...}})more or less node.js style events
constmodel=SuperModel()model.on.myevent((...values)=>{// ... do somethingconsole.log(...values)})model.emit.myevent('new','values')// ormodel.emit('myevent','newer','values')stop event listeners
constmodel=SuperModel()constoff=model.on.happening(()=>{})off()// no longer happeninginternally all values are stored in a map
constmodel=SuperModel()model.store// -> Map{"key":"value"}// setmodel('key','value')model({key: 'value'})model.key='value'// getmodel('key')// -> valmodel.key// -> valmodel.async.key// -> promise.then(val => {...})// deletemodel.del('key')deletemodel.keythere are 3 mutation types set, get, delmodel.on('type:key', val => {})model.on('type', (key, val) => {})
constmodel=SuperModel()model.on('set:existentialism',val=>{// render to dom or something...})// ormodel.on.set((key,val)=>{if(key==='existentialism'){// ...}})model.existentialism='What ever matters to you.'sync model values with other objects.sync(obj, key, modelProperty = key),.sync.stop(obj, key)
constmodel=SuperModel()model({PhilosophyOfTheDay: 'pragmatism'})constPHODelement=document.querySelector('#PHOD')// this keeps obj[key] updated with model[prop]model.sync(PHODelement,'textContent','PhilosophyOfTheDay')if(nolongerToday){// this will update the element's textmodel.PhilosophyOfTheDay='nominalism'}elseif(fedUpWithPositivism){model.PhilosophyOfTheDay='critical-realism'}// stop syncingmodel.sync.stop(PHODelement,'textContent').emitAsync is the same as .emit
it's just less slightly blocking by running the event loop
and each event listener in a setTimeout(ln, 0)
constmodel=SuperModel()model.emitAsync('evtType', ...['values'])