summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Lumme <erik@vaadin.com>2017-09-12 11:01:45 +0300
committerErik Lumme <erik@vaadin.com>2017-09-12 11:01:45 +0300
commit0a170337e580387566fee1af46c9537cdc8d62db (patch)
tree19f434047141fe2bfa514b21d767ffba2fc098ab
parent84e702dacadecb38815a6b43afff8d4609349a6b (diff)
downloadvaadin-framework-0a170337e580387566fee1af46c9537cdc8d62db.tar.gz
vaadin-framework-0a170337e580387566fee1af46c9537cdc8d62db.zip
Migrate IntegratingAJavaScriptComponent
-rw-r--r--documentation/articles/IntegratingAJavaScriptComponent.asciidoc101
-rw-r--r--documentation/articles/contents.asciidoc1
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]