Disclaimer
This how-to will show "a" way to construct a basic website using TypeScript, jQuery, KnockoutJS, and RequireJS. There are many other ways to do it.
Getting Started
Install Visual Studio Extension
Install Visual Studio 2012 extension - TypeScript for Microsoft Visual Studio 2012 PowerTool 1.0.1.0
http://visualstudiogallery.msdn.microsoft.com/ac357f1e-9847-46ac-a4cf-520325beaec1
Create new Visual Studio Project
- Start visual studio 2012.
- Select menu item "File"->"New"->"Project..."
- Navigate to "Templates"->"Other Languages"->"TypeScript" (this
actually creates a project file with extension .csproj - weird)
- Select Project Type "HTML Application with TypeScript"
Cleanup
Remove file app.css, app.ts from project
Add Components
Using NuGet, add...
- RequireJS (I selected version 2.1.15 for this tutorial)
- KnockoutJS (I selected version 3.2.0 for this tutorial)
- jQuery (I selected version 2.1.1 for this tutorial)
- requirejs.TypeScript.DefinitelyTyped (I selected version 0.2.0 by
Jason Jarrett for this tutorial. it installed a typescript def file
by Josh Baldwin - version 2.1.8 )
- knockout.TypeScript.DefinitelyTyped (I selected version 0.5.7 by
Jason Jarrett for this tutorial)
Setup Project Folders
Create project folders at root of project
- Application
- Models
- ViewModels
Create a basic TypeScript model
Add TypeScript file to project folder "Models"
- Right-click the folder "Models" in the Solution Explorer
- select context menu item "Add"->"New Item..."
- In left-hand pane, highlight "Visual C#"
- In right-hand pane, highlight "TypeScript File"
- In file name text box, enter "myTestModel.ts" Click button "Add"
Modify file "myTestModel.ts"
class myTestModel {
public fieldZ: string;
public fieldY: string;
public fieldX: number;
}
export=myTestModel;
Create a TypeScript view-model
Add TypeScript file to project folder "ViewModels"
- Right-click the folder "ViewModels" in the Solution Explorer
- select context menu item "Add"->"New Item..."
- In left-hand pane, highlight "Visual C#"
- In right-hand pane, highlight "TypeScript File"
- In file name text box, enter "myViewModel.ts"
- Click button "Add"
Modify file myViewModel.ts...
/// <reference path="../Scripts/typings/knockout/knockout.d.ts" />
import myTestModel = require("Models/myTestModel");
import ko = require("knockout");
class myViewModel {
public myString: KnockoutObservable<string>;
public myNumber: KnockoutObservable<number>;
public myComplexObject: KnockoutObservable<myTestModel>;
constructor() {
this.myString = ko.observable("some test data");
this.myNumber = ko.observable(987);
var tempComplexObject = new myTestModel;
tempComplexObject.fieldZ = "some bogus test data";
tempComplexObject.fieldY = "another bogus test data";
tempComplexObject.fieldX = 123;
this.myComplexObject = ko.observable(tempComplexObject);
}
myButton_Click() {
alert("I was clicked");
}
}
export=myViewModel;
Add configuration
Add RequireJS configuration file
- Right-click project folder "Application" in the Solution Explorer
- select context menu item "Add"->"New Item..."
- In left-hand pane, highlight "Visual C#"
- In right-hand pane, highlight "TypeScript File"
- In file name text box, enter "require-config.ts"
- Click button "Add"
Modify file "require-config.ts"
/// <reference path="../Scripts/typings/requirejs/require.d.ts" />
require.config({
baseUrl: "",
paths: {
"jQuery": "Scripts/jquery-2.1.1",
"knockout": "Scripts/knockout-3.2.0.debug",
"myViewModel": "ViewModels/myViewModel"
},
shim: {
"jQuery": {
exports: "$"
}
},
});
require(["jQuery"], function ($) {
$(document).ready(function () {
require(["knockout", "myViewModel"], (knockout, myViewModel) => {
var viewModel = new myViewModel;
knockout.applyBindings(viewModel);
});
});
});
Modify existing file index.html
Need to align the view with the view model.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>TypeScript HTML App</title>
<script data-main="Application/require-config" src="Scripts/require.js"></script>
</head>
<body>
<h1>TypeScript HTML App</h1>
<div id="myStringTest" data-bind="text: myString"></div>
<input id="myStringTest2" data-bind="value: myString" />
<input id="myNumberTest" data-bind="value: myNumber" />
<input id="myComplexObjectTest" data-bind="value: myComplexObject().fieldZ" />
<button id="myMethodTest" data-bind="click: myButton_Click" >click me</button>
</body>
</html>
Run it
OK - time to give a try. Comple, set some breakpoints in the .ts files, and hit F5.
Conclusion:
As you can see, there is not a lot of code in the example. If you run the example, and click the button you will find the button on index.html is bound to a method in myViewModel.ts called myButton_Click. Also, the text box myStringTest2, and myNumberTest are bound to variables defined in the view model.
The require-config.ts file holds the list of dependencies that are wired up. The line "knockout.applyBindings(viewModel)" associates the instance of myViewModel with the html view.
Notice how TypeScript allows variables to be declared with a data type?
I hope this primer helps. Just laying the several pieces on the table helped me visualize how these components play together. KnockoutJS has some cool plug-ins - such as knockout-mapping - which allows data pulled from a web service to be directly bound to the view model with no intermediate transformation or translation. Also, knockoutjs can support templating - presumably so master pages can be implemented.
For completeness, I will add a project folder called Views, and hold my html there. I think that is more traditional for MVC/MVVM development. The url having .html is still nagging me. I like MVC-style routing (no file extensions), but this is pretty cool too - especially since its nothing more than HTML and JavaScript - truly cross platform. Aside from web services calls (not included in the example) there are no postbacks, client side processing is fast.
Please feel free to comment...