View model

The model contains variables and methods which are bound to from the view's HTML. The view model should only contain business logic and no GUI logic. All GUI logic should be done using either bindings or in the view "code-behind" class.

The view model class

Every view model (automatically) implements IVistoViewModel (TypeScript interface). If the view model JavaScript file is not found, a generic/empty view model is created (the properties below are always available).

Methods on IVistoViewModel
  • Event methods
  • subscribe(observable, callback)
    • subscribes the callback on the observable and adds the subscription to the disposables array
    • registers a changed callback on the observable. the view model holds a reference to the subscription and closes it on destroy...
    • See also Avoiding memory leaks

Properties on IVistoViewModel
  • view
    • Reference to the view object. This property should not be used as it creates a high coupling with the view which is against the MVVM pattern.
  • parameters
  • viewManager
    • The Visto view manager object (can also be imported with RequireJS)
  • observableSubscriptions
    • Add observable.subscribe() results to this array to have them automatically disposed if the view is destroyed. This array is used by the subscribe method described above.

JavaScript implementation

define (["exports"], function (exports) {
	function SampleViewModel() { }

	SampleViewModel.prototype.initialize = function (parameters) {
		var self = this; = parameters.getObservable("bar", "default");
	exports.SampleViewModel = SampleViewModel;

TypeScript implementation

The inheritance and generics are needed to provide the best IntelliSense experience possible.

View model without view "code-behind":

import visto = module("libs/visto");
export class SampleViewModel extends VistoViewModel<IVistoView> {
	foo: KnockoutObservable<string>;
	initialize(parameters: VistoParameters) { = parameters.getObservable<string>("bar", "default");

View model with view "code-behind":

import visto = module("libs/visto");
import ns = module("../views/SampleView");
export class SampleViewModel extends VistoViewModel<ns.SampleView> { 
	loaded() {; // typed access to view "code-behind" members

Dialog view model without view "code-behind":

import visto = module("libs/visto");
export class SampleDialogModel extends VistoViewModel<IVistoDialog> {
	loaded() {
		var dialog = this.view.dialog; // only available with IVistoDialog
Note: The current TypeScript implementation does not allow to strongly type the view AND view model class because this causes a circular dependency and a stack overflow in the RequireJS even if the dependencies are only for typing... See TODO: Eventually remove view property on VistoView?

Last edited Jun 24, 2013 at 9:01 PM by rsuter, version 29


No comments yet.