TypeScript uMVC based on <https://github.com/petermichaux/uMVC>
abstract class Observer { | |
abstract update(data?: any): void | |
} | |
abstract class Observable { | |
protected _observers: Observer[] = [] | |
observe(observer: Observer) { | |
if (this._observers.indexOf(observer) > -1) | |
throw new Error('Observer already added') | |
this._observers.push(observer) | |
} | |
unobserve(observer: Observer) { | |
if (this._observers.indexOf(observer) == -1) | |
throw new Error('Observer does not exist') | |
this._observers = this._observers.filter(o => o === observer) | |
} | |
notify(data: any) { | |
// copy array before update in case one of the updates modifies the array | |
this._observers.slice(0).forEach(o => o.update(data)) | |
} | |
} | |
abstract class Model extends Observable {} | |
abstract class View extends Observer { | |
protected _parent?: View | |
protected _subViews: View[] = [] | |
constructor(protected _model: Model, protected _controller: Controller) { | |
super() | |
} | |
getController() { | |
return this._controller | |
} | |
getModel() { | |
return this._model | |
} | |
setModel(model: Model) { | |
this._setModelAndController(model, this._controller) | |
} | |
setController(controller: Controller) { | |
this._setModelAndController(this._model, controller) | |
} | |
protected _setModelAndController(model: Model, controller: Controller) { | |
if (this._model !== model) { | |
this._model.unobserve(this) | |
model.observe(this) | |
this._model = model | |
} | |
controller.setView(this) | |
controller.setModel(model) | |
this._controller = controller | |
} | |
getSubViews() { | |
return new Array(this._subViews) | |
} | |
addSubView(subView: View) { | |
var previousSuperView = subView.getSuperView() | |
if (previousSuperView) | |
previousSuperView.removeSubView(subView) | |
this._subViews.push(subView) | |
subView.setParent(this) | |
} | |
removeSubView(subView: View) { | |
this._subViews = this._subViews.filter(s => { | |
if(s === subView) | |
s.setParent(undefined) | |
return s !== subView | |
}) | |
} | |
setParent(parent?: View) { | |
this._parent = parent | |
} | |
getSuperView() { | |
return this._parent | |
} | |
destroy() { | |
this._model.unobserve(this) | |
this._subViews.forEach(s => s.destroy()) | |
} | |
} | |
abstract class Controller { | |
protected _model?: Model | |
protected _view?: View | |
getModel(): Model | undefined { | |
return this._model | |
} | |
setModel(model?: Model) { | |
this._model = model | |
} | |
getView(): View | undefined { | |
return this._view | |
} | |
setView(view?: View) { | |
this._view = view | |
} | |
} | |
export {Model, View, Controller} |
This comment has been minimized.
This comment has been minimized.
Line 8: arrow function missing logical not. |
This comment has been minimized.
This comment has been minimized.
Thanks for the comment. I've changed the implementation to TypeScript to make the usage clearer. You can compile this to the version of JavaScript desired here. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Very nice example!
While copying into my notebook, I noticed 2 tiny errors. Line 31: misleading indentation. Line 76: missing underscore in '_subViews'.