In this article I will tell you how I implemented beautiful graphics in our utility accounting service
Dom24x7 and what problems and inconveniences I had to face.
For Vaadin 7 there is a great official addition to working with charts, but the problem is that it is not free and costs almost $ 500! I didn’t want to spend such money, and I decided to look for an alternative from the free one, but unfortunately, all I found was completely dissatisfied with the quality and then I turned my attention to the official supplement for working with charts and decided to study it more closely.
It turned out that this addition is just a shell for the excellent javascript library
Highcharts , which, miraculously, could be used free of charge in non-commercial projects (which, at the moment, is our project, although, when its status changes, I will be happy to purchase a commercial license ), although there is still a wonderful alternative library
Amcharts , but still decided to stay at the previous one.
')
By the way, the developers of Vaadin explain why they ask so much for supplementing working with charts by the fact that they have to acquire a corporate license.
Having decided on the library, it remains to decide the question, how can we connect it to our project?
The article consists of two parts. The first part is a translation of an article on how to connect the javascript library to vaadin projects, and the second part will tell you about how I, using this knowledge, wrote the library to display graphs.
So…
Vaadin 7 loves javascript components
Using JavaScript components in Vaadin 7 is easy. Of course, Vaadin has long had a
Window.executeJavaScript () method, but this method has quite a few limitations. For example, if you have dependencies with Javascript files, it is difficult to guarantee their loading before calling.
Like other Vaadin 7 GWT components, the JavaScript component consists of 4 parts:
- server component (server-side component),
- state
- connector
- and the client component is a widget (client-side widget).
In simple examples (for example, as discussed below), it is easier to combine the connector and the client widget. However, associating a ready-made javacscript widget with the functionality of the Javascript component, you write only the connector itself that will control the widget (which is the library).
Almost everything you can do with a GWT widget, you can also do with a JavaScript widget. Below we look at a simple example to show how its various parts work.
In the example below, we simply display a message.
Server side
@JavaScript({ "js_label.js" }) public class JsLabel extends AbstractJavaScriptComponent { public JsLabel(String xhtml) { getState().xhtml = xhtml; } @Override protected JsLabelState getState() { return (JsLabelState) super.getState(); } }
As we can see, our component is very simple. It declares only a constructor with one parameter - the text that needs to be displayed. This parameter is transmitted to the client side using the general state. An important part of the code is the annotation that extends the JsLabel class.
JavaScript tells Vaadin about any JavaScript files your widget needs. In our example, only js_label.js is required, which is an implementation of the client side of JsLabel. Since we specified the relative path to the file, it should be in the same java-package as the JsLabel class. Thus, in my IDE, js_label.js and JsLabel.java are located nearby. If necessary, you can list several files as a string array in
JavaScript annotation, or you can also specify the path in the URL format.
AbstractJavaScriptComponent is a class that we extend. It allows you to create a two-way connection between javascript and vaadin, using a common state object.
Note that Vaadin knows which state class is being used, because we override the getState () method to work with our generic state class. This behavior is not specific to JavaScriptComponent, but is characteristic of all components of Vaadin 7.
State definition
public class JsLabelState extends JavaScriptComponentState { public String xhtml; }
The sole purpose of the state object is to transfer data between the server and the client side, both ways. To create it, you need to extend JavaScriptComponentState.
To keep our code concise and symmetrical by JavaScript (as you will see below), I decided to define the xhtml field as public. Nothing prevents us from adding getter and setter there, but since the state class is only for data transfer and there is no logic in it (and should not be present there), getter and setter are not needed for fields in our case.
Note: You can make the state class an internal JsLabel class to shorten the code. The problem with this approach is that the built-in state classes only work with JavaScript components. Generic state classes for GWT do not work as inner classes, except in some special cases. In addition, if for some reason we don’t want to call the getState () method, we don’t forget to manually call the markAsDirty () method each time we change the state. Therefore, to avoid confusion, it is strongly recommended that state classes be kept separate from the component.
Client side
org_vaadin_blog_JsLabel = function() { var e = this.getElement(); this.onStateChange = function() { e.innerHTML = this.getState().xhtml; } }
It is this js_label.js file that we specified in
JavaScript annotation earlier. Here you need to pay attention to two things: the name of the function and the use of this.
There is a naming convention that we must follow. This helps Vaadin properly find the JavaScript function to call it when our component is used. We take the full class name of the server component and simply replace the dots with an underscore. In our case, the JavaScript function should be called org_vaadin_blog_JsLabel. Do not worry, if you are mistaken in the name, then Vaadin will tell you how (in his opinion) the function should be called.
Additional information can be found in the JavaDoc class AbstractJavaScriptComponent (link to
alpha 3's JavaDoc . In the example, we use only this.getElement () to get the DOM element that was created for our Vaadin widget and this.getState () to access the state In our case, we read the XHTML string from the state and insert it into the DOM element innerHTML. Unfortunately, the state component cannot be updated on the client side so that these changes are received on the server side.
As mentioned above, this file is a connector and a widget at the same time. The duty of the connector is to link the state and the widget. In our case, the separation would only complicate the code, so we merged the widget and the connector in one javascript file.
Please note that any getters and setters in the state cannot be used on the JavaScript side and we work with fields as with normal properties. This is true even when you explicitly write access methods in your state class.
Thus, we have a convenient mechanism for connecting the JavaScript component with existing widgets (js libraries). This is useful when you own JavaScript and want to program small and fast client-side functions. But GWT is still the best alternative for building more complex and reliable components for Vaadin.In the next article I will describe in detail how, using this knowledge, I created a javascript shell for the Highcharts charting library.