Getting TypeScript to Work with a LightSwitch HTML Project (kind of)

Last week I saw a post on the LightSwitch forum that pointed out that steps outlined in a blog post by Michael Washington regarding using TypeScript in a LightSwitch project were no longer working. So I thought I would go through the blog post and try it out. I hadn’t done anything with TypeScript before so this was my first experience. The steps outlined in Michael’s blog post definitely didn’t work anymore and it ended up taking me a while to figure out how to get things “working” (in air quotes), so I figured I’d post about it.

To start, here’s a brief summary of the issues I ran into:

  • There was no entry in the “Add” context menu for “TypeScript File” when right-clicking on the HTMLClient project (i.e. the .jsproj)
  • There was no entry for “TypeScript File” in the “Add New Item” dialog
  • When I added a new JavaScript file and renamed it to end with a .ts extension, I couldn’t get the .ts file to compile and generate the corresponding .js file (I tried a variety of different things here that I won’t get into)

I did find an open bug that was something along the lines of “TypeScript should work with JavaScript projects (.jsproj)” so hopefully these will all be addressed in the near future.

Here is what I needed to do to get things to work:

Close VS

Find the .jsproj file in the HTML sub-project’s folder and open it with Notepad

image

Insert the bolded entries just below the first PropertyGroup node near the top of the file:

 

<PropertyGroup Condition=" '$(Configuration)' != 'Release' ">
  < UseDesignTimeFeatures>true</UseDesignTimeFeatures>
< /PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
< TypeScriptTarget>ES5</TypeScriptTarget>
< TypeScriptRemoveComments>false</TypeScriptRemoveComments>
< TypeScriptSourceMap>true</TypeScriptSourceMap>
< TypeScriptModuleKind>AMD</TypeScriptModuleKind>
< /PropertyGroup>
< PropertyGroup Condition="'$(Configuration)' == 'Release'">
< TypeScriptTarget>ES5</TypeScriptTarget>
< TypeScriptRemoveComments>true</TypeScriptRemoveComments>
< TypeScriptSourceMap>false</TypeScriptSourceMap>
< TypeScriptModuleKind>AMD</TypeScriptModuleKind>
< /PropertyGroup>
< Import Project="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\TypeScript\Microsoft.TypeScript.targets" />
< Import Project="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\TypeScript\Microsoft.TypeScript.jsproj.targets" />

<PropertyGroup Label="Globals">

I stole this snippet from a new TypeScript project that I had created and after some spelunking online found various sources that said that these are the meaningful parts regarding JavaScript generation (I changed the Import nodes to use absolute paths instead of environment variables because it didn’t work with the environment variables on some machines). Note that you need to remove all the leading spaces in front most of the elements (LiveWriter insists on adding these during the publish process, sorry).

 

Open your LightSwitch project in VS and choose to add a new JavaScript file to the HTMLClient project

image

 

Change the name of the file to end with .ts instead of .js

image

 

Paste this code into the file that was just created (this is taken from Michael’s blog post)

 

 class FormatName {
    _firstname: string;
    _lastname: string;
    _age: number;
    constructor(
        firstname: string,
        lastname: string,
        age: number
        ) {
        this._firstname = firstname;
        this._lastname = lastname;
        this._age = age;
    }
    ReturnName() {
        var formatedName =
            this._lastname.toUpperCase()
            + ", " +
            this._firstname.toLowerCase()
            + " {" + this._age.toString() + "}";
        
         return formatedName
       }
}

 

Then save the file. Now what should have happened is that a .js file was generated and added to the .jsproj. The .js file is created, but it isn’t added to the project

image

 

image

So, we need to manually add this to the project by performing Add >> Existing Item and selecting the .js file from the browse window that opens

image

 

Now the .js file will be copied out to the Scripts folder when you do a build. Finally, you will need to add an entry in the HTMLClient project’s default.htm to include this new file

<script type="text/javascript" src="Scripts/Generated/generatedAssets.js"></script>

<script src="scripts/formatname.js"></script>
<script type="text/javascript">

After all this, we now have generated JavaScript that we can call from the JavaScript files that are generated when you “Add Code” to a screen. Here’s an example (again taken from Michael’s blog). This example is for the “postRender” code for a List (notice the lines using FormatName and ReturnName).

 myapp.BrowsePeople.rows_render = function (element, contentItem) {
    // Write code here.
    var itemTemplate = $("<div></div>");
    var FirstName = contentItem.data["FirstName"];
    var LastName = contentItem.data["LastName"];
    var Age = contentItem.data["Age"];
    var objFomatName = new FormatName(FirstName, LastName, Age);
    var FinalName = $("<h1>" + objFomatName.ReturnName() + "</h1>");
    FinalName.appendTo($(itemTemplate));
    itemTemplate.appendTo($(element));
};

So that is something, not much, but something. We got some good feedback on the forums about ways we could improve the experience for supporting TypeScript from a LightSwitch project. Hopefully we can deliver on some improvements in the future.

A sample project for the sample described here can be found at https://code.msdn.microsoft.com/Using-TypeScript-with-c418131a

Comments

  • Anonymous
    June 02, 2014
    I updated my blog post to point to your new post :)

  • Anonymous
    June 02, 2014
    "So, we need to manually add this to the project by performing Add >> New Item and selecting the .js file from the browse window that opens" I think this should be "Add >> Existing Item", as shown in the following screenshot.

  • Anonymous
    June 03, 2014
    Thank Dave, but this isn't working for me. A few things I've noticed:

  1. Your "PropertyGroup" includes are getting pretty mangled by your blog formatting. But I got the drift, added a TypeScript project and copied the text from there.
  2. When I add a .ts file like you describe, it does not generate the .js like you described. I'm still researching this, but are you sure you didn't have to do anything else? Just FYI: I have the VS2013 update 2, and can add a separate TypeScript project I'll update this as I find new information. Cheers...
  • Anonymous
    June 03, 2014
    @Simon - thanks, my bad @batpox - The file doesn't get generated immediately, you have to put something in the TypeScript file first and save it.  Assuming you tried that though.  Tomorrow I will look into posting my project to CodePlex so you can download it and compare it to what you have.

  • Anonymous
    June 03, 2014
    Thanks Dave, it is very much appreciated and I look forward to it. If I can just get it to automatically build to the .js as you describe, it will satisfy my requirements. Nonetheless, it has been an education exploring the msbuild, the targets, and what-not. My TS file has the TS Icon, and everything seems to point to the correct msbuild TypeScript folder (which has, I believe, the correct targets and TypeScript dll, but nothing is generated and I can find no errors. So again, thanks, and I look forward to seeing your project.

  • Anonymous
    June 04, 2014
    The comment has been removed

  • Anonymous
    June 05, 2014
    I do appreciate your efforts. I will also keep digging as well and post here when I find something. It seems odd that MS would spend some serious money on such a (potentially) wonderful tool, bake it into Visual Studio, and then not provide a decent and consistent way to use it. I sometimes think MS has a serious attention deficit problem. Maybe it is part of their ARF (Announce, Release, and Forget) policy :)   Thanks again!

  • Anonymous
    June 05, 2014
    I updated the .jsproj snippet with a couple more lines and got it to work on the other machine (the two Import statements).  I have uploaded a sample to here: code.msdn.microsoft.com/Using-TypeScript-with-c418131a As far as your other comments, all I can say is there's a lot of people here that work on a lot of different stuff at a very fast pace, so it can be very difficult to get things right on the first try.  Thankfully, now that we have a more frequent cadence for VS Updates, we can get improvements out faster.

  • Anonymous
    June 05, 2014
    Thanks Dave, that did the trick. Hopefully VS2013 Update 3 will do this a bit cleaner. I really like LightSwitch and the extensibility that JavaScript provides, and TypeScript (IMHO) fixes most of JavaScript shortcomings. I notice you are on the test team. Perhaps next you could look at the very slow performance when you have 80 database tables (we end users are never satisfied, you know :) BTW: I marked you as answering my question. Thanks again!

  • Anonymous
    January 05, 2015
    The comment has been removed

  • Anonymous
    January 05, 2015
    Just an addendum to my last post. I'm not suggesting that you put any of the generated "myapp.someMethodName" code into ts files in the "UserCode" folder. I tried using TS for that a while back (in the "Screens" folder), but it was more hassle than it was worth. I would only the put the code that I call from those methods. That reminds me that I need to write a complete blog post on how I avoid polluting the global scope like LightSwitch does by default. I'll put it on the list sigh