Combining Fuse with TypeScript

Introduction

It’s not a secret that es5 now looks a little bit silly.
As a frontend engineer with love to TypeScript, i have a suggestion how to use TypeScript/ECMAScript2015 in Fuse.
First of all, the same technique can be applied to use es6 and babel, but for now i will describe steps to use TypeScript.

Step 1:

Install typescript and typings. To do this you need to do:

npm install typescript -g
npm install typings -g

Step 2:

Create a tsconfig.json file inside your project folder.
Here is example of tsconfig:

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "declaration": false,
        "noImplicitAny": false,
        "removeComments": true,
        "noLib": false
    }
}

Step 3:

Now just create a TS file and run

 tsc --watch

Step 4:

Inside your .ux file just reference compiled js file like so

<JavaScript File="{TSFileName}.js"/> 

Example

MainView.ts:

const Observable = require("FuseJS/Observable");

class ViewModel{
	public name = Observable("TestVal");
	public test = Observable("");
}

export const vm =  new ViewModel();

MainView.ux:

<App>
    <ClientPanel>
    	<JavaScript File="MainView.js"/>
        <StackPanel>
        	<Text Value="{vm.name}"/>
        	<TextBox Value="{vm.name}"/>
    	</StackPanel>
    </ClientPanel>
</App>

FAQ:

TypeScript compiler error ‘require’ is undefined

**Answer: ** Just open terminal and install node typings:

npm install @types/node --save-dev

TypeScript Official site

Stage 2. Working with TS Classes

After testing that TS classes works, we need to be able to call TS functions from UX.
Well, it’s not as simple as it could be, but there are still possibility to use typescript in Fuse:)

First of all. If we define function inside TS class like this:

export class ViewModel{
	public name = Observable("TestVal");
	validate():boolean{
		console.log("validation method called. Context variable:" + this.name.value);
		return true;
	}
}

And then in .ux file write smh like this:

<Button Clicked="{vm.validate}"/>

We will receive absolutely nothing.
So, let’s see what can we do.
First of all, each time Clicked event is called, we will receive whole page context which will be stored in args.data.
Let’s define few interfaces. This will help us keep static typing of our application.

interface EventArgs{
	data:PageData
}
interface PageData{
	vm:ViewModel;
}

Now, we have to export our method which will call our ViewModel’s validate method.

export const validateEmail:(args:EventArgs)=>boolean = (args:EventArgs)=>{
	let {vm} = args.data; // this syntax means that we will take args.data.vm and create local variable vm of type ViewModel
	return vm.validate();
}

That’s it! If we now write:

	<MyButton Text="Click me"  Clicked="{validateEmail}"/>

This will call validateEmail method, which is exported by our .ts file, which then will take our context, and call validate() method on vm object.

Here is how final .ts file looks like:

const Observable = require("FuseJS/Observable");

interface EventArgs{
	data:PageData
}
interface PageData{
	vm:ViewModel;
}

export class ViewModel{
	public name = Observable("TestVal");
	validate(){
		console.log("validation method called. Context variable:" + this.name.value);
		return true;
	}
}
export const vm = new ViewModel();

export const validateEmail:(args:EventArgs)=>boolean = (args:EventArgs)=>{
	let {vm} = args.data;
	return vm.validate();
}

Very cool! Thanks for sharing!

Anders Lassen wrote:

Very cool! Thanks for sharing!

It would be nice if we could call methods from objects inside .ux.
It’s a little bit strange that i can’t call method on object:(

Yes, this is all coming. A lot of work is being done on the Fuse side to make UX expressions more powerful :slight_smile:

Anders Lassen wrote:

Yes, this is all coming. A lot of work is being done on the Fuse side to make UX expressions more powerful :slight_smile:

Is Fuse open-source or is there any ways to see what’s happening inside?

It is sort of open source, we give out code on request if there is a point in doing so (e.g. for debugging). But, at the moment it is not being actively run as an open source project (not accepting PRs, no open issue tracker, no public repos).

We are however working in the direction of open sourcing it - it’s just a matter of having the resources to do it properly.

Anders Lassen wrote:

It is sort of open source, we give out code on request if there is a point in doing so (e.g. for debugging). But, at the moment it is not being actively run as an open source project (not accepting PRs, no open issue tracker).

We are however working in the direction of open sourcing it - it’s just a matter of having the resources to do it properly.

Well, i might be looking to write some framework-over-framework :smiley:
It would be nice if you share some specific information about how to get router and other parts, using some Dependency Injection or smth like that. To be able to write app logic outside of .ux components.

Have a look at the <Closure> tag. It was designed to allow an alternative way of accessing all the symbols in an UX scope (beyond the implicit injection that happens in a <JavaScript> tag).

https://www.fusetools.com/docs/fuse/reactive/closure

Used like this:

  <Closure Ready="{handler}" />

If e.g. router is defined in the scope of the closure, then you have:

   function handler(arg) {
          arg.router  // <-- here you go
   }

Anders Lassen wrote:

Have a look at the <Closure> tag. It was designed to allow an alternative way of accessing all the symbols in an UX scope (beyond the implicit injection that happens in a <JavaScript> tag).

Fuse

Used like this:

  <Closure Ready="{handler}" />

If e.g. router is defined in the scope of the closure, then you have:

   function handler(arg) {
          arg.router  // <-- here you go
   }

Nice!
I would see if i can split ui from logic.

Hey Vladimir thank you for your post and mini-tutorial.

I wanted to ask if you had put together a Typings file for Fusetools yet, and if this may be worthwhile?