Skip to content

Instantly share code, notes, and snippets.

@mlhaufe

mlhaufe/uMVC.ts

Last active Oct 5, 2019
Embed
What would you like to do?
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

This comment has been minimized.

Copy link

@luser-dr00g luser-dr00g commented Oct 5, 2019

Very nice example!

While copying into my notebook, I noticed 2 tiny errors. Line 31: misleading indentation. Line 76: missing underscore in '_subViews'.

@luser-dr00g

This comment has been minimized.

Copy link

@luser-dr00g luser-dr00g commented Oct 5, 2019

Line 8: arrow function missing logical not.

@mlhaufe

This comment has been minimized.

Copy link
Owner Author

@mlhaufe 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
You can’t perform that action at this time.