Skip to content

Repository files navigation

👯 SuperModel.js 👯

Harness the power of proxies!

JavaScript Style Guide

  • +: 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

API

  • 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 property
  • model(key, =val)- shorthand function based property get/set
  • model({...props})- update properties with an object
  • model[prop]- get/set model property
  • model.async[prop]- get/set model property using promises
  • model.valid(key, =validator)- make a property validate-able by adding a validator func/RegExp
  • model.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

Learn By Example

Async/Await Values

// 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()

Data Binding

<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')

Validate Properties

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'){// ...}})

Emit Events

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 happening

Mutations

internally 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.key
listening to mutation events

there are 3 mutation types set, get, del
model.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.'

other things

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'])

About

Manage your app's state like never before, harness the power of the proxy! 👯

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages