Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create basic TypeScript project using jQuery, RequireJS, and KnockoutJS

I have been searching for a simple how-to, to create the most basic example of a Visual Studio 2012 TypeScript project utilizing RequireJS, jQuery, and KnockoutJS. There are several examples available, but for me some where more complicated than I wanted so I set out to create a how-to, and have posted it here for public scrutiny. I have answered my own question as a Q&A style knowledge sharing exercise.

For those unfamiliar, here is a quick breakdown of the included components...

TypeScript - A Visual Studio extension that allows scripting to create a .TS file via a language that is a superset of JavaScript. This provides the ability to define a data type associated with methods and variables - which is otherwise missing from JavaScript. By doing so, compile time checks can ensure the proper use in an attempt to reduce run-time conflicts. When building the Visual Studio project, the Visual Studio extension will compile the script into actual JavaScript. As such, this extension comes with it's own compiler - tsc.exe. It is expected the resulting JavaScript files will be deployed to production, not the source code .ts files.

jQuery - a JavaScript framework for HTML document traversal and manipulation, event handling, animation, and Ajax interaction.

RequireJS - Dependency loader. Sometimes JavaScript references can get crazy. This attempts to assist with these concerns. My example shows that even though many JavaScript files are in use, the HTML only refers to one - the root JavaScript file that loads the others.

KnockoutJS - UI binding, utilizing the MVVM pattern. HTML views refer to variables and methods in a view-model. The view model is a JavaScript object (the JavaScript file is likely the result of compiling a .ts file - see TypeScript above).

DefinitelyTyped - Also included are two DefinitelyTyped NuGet packages. Because TypeScript is attempting to verify data type usage, it is performing a check to ensure it is aware of all references. JavaScript is a bit more loose than that. In order to satisfy TypeScript (when referring to external JavaScript objects) we need a way to describe (to TypeScript) the objects we expect to be used. These DefinitelyTyped scripts provide this definition. They provide no functionality, just clarity to the TypeScript compiler so it can perform these checks.

In the example below, you will see

/// <reference path="../Scripts/typings/requirejs/require.d.ts" />

This is how the TypeScript compiler will include the requirejs DefinitelyTyped definition file. The organization creating these DefinitelyTyped scripts have created a vast collection. Here we refer to only two - KnockoutJS, and RequireJS (well, because that is the scope of this tutorial)

like image 265
barrypicker Avatar asked Sep 18 '14 23:09

barrypicker


1 Answers

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...

like image 66
barrypicker Avatar answered Sep 16 '22 16:09

barrypicker