Skip to content

Instantly share code, notes, and snippets.

@mlhaufe
Last active October 5, 2019 18:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mlhaufe/c841b2269b0099c3c52648717f9551cc to your computer and use it in GitHub Desktop.
Save mlhaufe/c841b2269b0099c3c52648717f9551cc to your computer and use it in GitHub Desktop.
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}
@luser-dr00g
Copy link

Line 8: arrow function missing logical not.

@mlhaufe
Copy link
Author

mlhaufe commented Oct 5, 2019

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