Blog

Creating Vaadin Components with TypeScript

By  
Matti Vesa
·
On Mar 10, 2015 12:45:00 PM
·

With the introduction of Vaadin 7 it became possible to write components using plain JavaScript. Doing so has the benefit of not having to compile the widgetset, and being able to use the browser development tools without devmode.

One of the downsides of using JavaScript is the lack of static typing and the security and clarity that comes with it. Things have changed since then, and typed JavaScript is on the rise. One of the more seasoned approaches to statically typed JavaScript is TypeScript. The language aims to provide static typing in addition to many of the upcoming ES6 features. It does not change the semantics of JavaScript which means that the resulting code is recognizable in browser dev tools.

This article is going to showcase using TypeScript for writing Vaadin Components. We are going to make most of the available typing mechanism to describe the API provided to plain JavaScript components and provide examples of communication between the client and the server.

Obtaining the necessary tools

Node.js is required for using TypeScript. While TypeScript can be installed through npm and used from the command line, Vaadin developers tend to use Eclipse to write code. There are a couple of TypeScript integrations for Eclipse: Typecs and typescript-plugin. Both use the same compiler in the background, so just try which one you like better.

Project structure

TypeScript components are developed much in the same way as JavaScript ones. The .ts files, or at least the resulting .js files, are placed either in the same directory as the server side widget using relative URLs, or anywhere in the classpath using absolute URLs. The server side widget extends from AbstractJavaScriptComponent and contains our .js file inside a JavaScript annotation:

@JavaScript({"DemoWidget.js"})

On the client side we have a function whose name is the package name, with periods replaced by underscores, followed by the name of the component class. For example:

var com_example_MyWidget = function() { }

The this object passed to this function is a Connector object that provides us all the hooks we need to get the same functionality as with GWT components. The needed interactions with server side include RPC and shared state.

Typed interfaces

The interfaces provided to JavaScript programmers by the Vaadin framework are a bit of a mystery. Since we are dealing with a dynamically typed language, there is no description of what is contained in the this object provided to the widget function, not to mention in objects that it contains. You can just refer to the documentation or inspect the object at runtime. Not that handy.

With TypeScript it becomes possible to create simple interface definitions that make everything crystal clear, just like any Java developer would expect. To the example project the basic JS API available for Vaadin components is declared in Vaadin.d.ts. The contents of Vaadin.d.ts corresponds to documentation of “this” for the connector found at https://vaadin.com/api/7.4.1/com/vaadin/ui/AbstractJavaScriptComponent.html, and also some observations done on the code constructing it.

Shared state

Shared state is simply an object with properties passed from the server to the client. There are some properties that the shared state of every Vaadin Connector has. Those can be found in the Connector interface defined in Vaadin.d.ts.

When the shared state changes, the function onStateChange is called. Override it in your widget to listen to those changes. When the function is called, new values can be read from the shared state object. The object can be obtained by calling this.getState(). Remember that this is our Connector instance.

RPC from server to client

RPC calls from server to client are done by using the callFunction method in AbstractJavaScriptComponent. The function name is provided as the first parameter, followed by any arguments it may have. The callFunction javadoc has this to say about the arguments: “The arguments should only contain data types that can be represented in JavaScript including primitives, their boxed types, arrays, String, List, Set, Map, Connector and JavaBeans.”

RPC from client to server

The other direction, from client to server, is only slightly more complicated. The RPC functions need to be registered by using the addFunction method in AbstractJavaScriptComponent. The method takes the function name and a JavaScriptFunction instance as parameters. After the method has been registered, it becomes available on the client side as a function in the Connector instance.

The JavaScriptFunction instance has a call method, which is invoked when the RPC call is made on the client side. Any parameters to the call are passed in a JsonArray instance as a parameter to the call method.

Conclusion

As we’ve seen, RPC and shared state are available and not too complex to use when developing components in TypeScript. The interface definitions found in example project’s Vaadin.d.ts clarify to the set of supplied functions and values from basic Vaadin JavaScript integration, and also give a starting point for organizing one’s own components.

Feel free to use the Vaadin.d.ts in your own projects (Apache 2.0 licenced) and in case you find out some improvement ideas, I’m more than happy to get contributions for the project.

Get the example program from GitHub

Matti Vesa
Matti Vesa has been hacking using Vaadin since 2010 as a Vaadin Expert
Other posts by Matti Vesa