diff options
author | Erik Lumme <erik@vaadin.com> | 2017-09-12 11:01:45 +0300 |
---|---|---|
committer | Erik Lumme <erik@vaadin.com> | 2017-09-12 11:01:45 +0300 |
commit | 0a170337e580387566fee1af46c9537cdc8d62db (patch) | |
tree | 19f434047141fe2bfa514b21d767ffba2fc098ab | |
parent | 84e702dacadecb38815a6b43afff8d4609349a6b (diff) | |
download | vaadin-framework-0a170337e580387566fee1af46c9537cdc8d62db.tar.gz vaadin-framework-0a170337e580387566fee1af46c9537cdc8d62db.zip |
Migrate IntegratingAJavaScriptComponent
-rw-r--r-- | documentation/articles/IntegratingAJavaScriptComponent.asciidoc | 101 | ||||
-rw-r--r-- | documentation/articles/contents.asciidoc | 1 |
2 files changed, 102 insertions, 0 deletions
diff --git a/documentation/articles/IntegratingAJavaScriptComponent.asciidoc b/documentation/articles/IntegratingAJavaScriptComponent.asciidoc new file mode 100644 index 0000000000..7762f14e04 --- /dev/null +++ b/documentation/articles/IntegratingAJavaScriptComponent.asciidoc @@ -0,0 +1,101 @@ +[[integrating-a-javascript-component]] +Integrating a JavaScript component +---------------------------------- + +You can use an existing JavaScript component as a component in Vaadin by +creating a server-side API for the component as well as writing the +JavaScript code that connects the server-side API to the actual +JavaScript component. Because of the dynamic nature of JavaScript, you +don't need to use GWT development mode or recompile the widgetset while +making client-side changes. + +The server-side component should extend `AbstractJavaScriptComponent` and +provide the API that the developer uses to interact with the component. +The class should also have a `@JavaScript` annotation that defines the +required JavaScript libraries in the order they should be loaded. This +example uses the Flot graph library from http://code.google.com/p/flot/. +Float requires jQuery which is loaded using +https://developers.google.com/speed/libraries/[Google Libraries API]. + +[source,java] +.... +import com.vaadin.annotations.*; + +@JavaScript({"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", "jquery.flot.js", "flot_connector.js"}) +public class Flot extends AbstractJavaScriptComponent { + public void addSeries(double... points) { + List<List<Double>> pointList = new ArrayList<List<Double>>(); + for (int i = 0; i < points.length; i++) { + pointList.add(Arrays.asList(Double.valueOf(i), + Double.valueOf(points[i]))); + } + + getState().series.add(pointList); + } + + @Override + public FlotState getState() { + return (FlotState) super.getState(); + } +} +.... + +The shared state class will not be used by any GWT code so you don't +have to put it in the widgetset's client package. The state class should +extend `JavaScriptComponentState` but is otherwise similar to the shared +state of a normal GWT component. + +[source,java] +.... +public class FlotState extends JavaScriptComponentState { + public List<List<List<Double>>> series = new ArrayList<List<List<Double>>>(); +} +.... + +The only remaining code is the client-side JavaScript connector in +`flot_connector.js`. The connector defines a global initializer function +named based on the fully qualified name of the server-side `Component` +class with dots replaced with underscores. In this example the +server-side `Component` is `com.example.Flot` which means that the function +name should be `com_example_Flot`. + +This initializer function should initialize the JavaScript part of the +component. It is called by the framework with `this` pointing to a +connector wrapper providing integration to the framework. For full +information about the services provided by the connector wrapper, please +read the Javadoc for the `AbstractJavaScriptComponent` class. + +In this example, the initializer first initializes the `element` +variable with a jQuery object for the DOM element of the component. +Next, a state change listener is defined by assigning a function to the +`onStateChange` field of the connector wrapper. This function will be +called whenever the shared state is changed from the server-side code. +In the state change listener, the Flot API is used to initialize a graph +with the data series from the shared state into the DOM element. + +The format of the series property in the `FlotState` Java class has been +chosen with the Flot API in mind. Flot expects an array of data series +where each item is an array of data points where each data point is an +array with the x value followed by the y value. This is defined in Java +as `List<List<List<Double>>>` and then the framework takes care of the +conversion between server-side Java values and client-side JavaScript +values. `double[][][]` in Java would give the same JavaScript structure, +but it was not used here as it gives less flexibility in the Java code. + +[source,java] +.... +window.com_example_Flot = function() { + var element = $(this.getElement()); + + this.onStateChange = function() { + $.plot(element, this.getState().series); + } +} +.... + +By implementing a server-side Java class extending +`AbstractJavaScriptConnector` and a client-side JavaScript connector +initialization function, existing JavaScript component libraries can +easily be integrated to Vaadin. The server-side code is almost similar +to the code required for a component based on GWT and the client-side +code is quite similar to a `ComponentConnector` implemented using GWT. diff --git a/documentation/articles/contents.asciidoc b/documentation/articles/contents.asciidoc index d8b62de75e..3b02b3d4d5 100644 --- a/documentation/articles/contents.asciidoc +++ b/documentation/articles/contents.asciidoc @@ -44,3 +44,4 @@ are great, too. - link:VaadinOnGrailsCreateProjectInIntelliJIDEA.asciidoc[Vaadin on grails - Create project in IntelliJ IDEA] - link:VaadinOnGrailsDatabaseAccess.asciidoc[Vaadin on grails - Database access] - link:VaadinOnGrailsMultipleUIs.asciidoc[Vaadin on grails - Multiple UIs] +- link:IntegratingAJavaScriptComponent.asciidoc[Integrating a JavaScript component] |