Last active
October 5, 2019 18:18
-
-
Save mlhaufe/c841b2269b0099c3c52648717f9551cc to your computer and use it in GitHub Desktop.
TypeScript uMVC based on <https://github.com/petermichaux/uMVC>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} |
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
Line 8: arrow function missing logical not.