2. Who am I
• Java (EE) Dev/Architect
• Vaadin enthusiast
• General blog
•
http://blog.frankel.ch
•
@nicolas_frankel
• Vaadin specific
•
http://morevaadin.com
•
@learnvaadin
3.
4. Extension points
1.
Compose base components
2.
Wrap GWT widgets
3.
Extensions
4.
Wrap JavaScript
5.
Theme
This presentation requires
you have a bare minimum
knowledge of Vaadin and
how it works
6. Composition
• It can’t be that hard
Just compose…
• Let’s create an Address component
And see for ourselves
7. First step
public class Address extends VerticalLayout {
public Address() {
}
}
addComponent(new
addComponent(new
addComponent(new
addComponent(new
TextField("Ligne 1"));
TextField("Ligne 2"));
TextField("Ville"));
TextField("NPA"));
8. Input vs label
TextField ligne1 = new TextField();
TextField ligne2 = new TextField();
TextField ville = new TextField();
TextField npa = new TextField();
ligne1.setInputPrompt("Ligne 1");
ligne2.setInputPrompt("Ligne 2");
ville.setInputPrompt("Ville");
npa.setInputPrompt("NPA");
addComponent(ligne1);
addComponent(ligne2);
addComponent(ville);
addComponent(npa);
9. Spacing
setSpacing(true);
TextField ligne1 = new TextField();
TextField ligne2 = new TextField();
TextField ville = new TextField();
TextField npa = new TextField();
ligne1.setInputPrompt("Ligne 1");
ligne2.setInputPrompt("Ligne 2");
ville.setInputPrompt("Ville");
npa.setInputPrompt("NPA");
addComponent(ligne1);
addComponent(ligne2);
addComponent(ville);
addComponent(npa);
10. Problems?
No choice between labels and input prompts
No choice between spacing or not
i18n
Fixed layout
And so on
No configuration feature!
11. Configuration design
Expose your configuration features
Wrap the rest
As for API
Introduce middle-components for decoupling
For layout, use CustomComponent
12. public class Address extends CustomComponent {
private Layout layout;
private TextField ligne1 = new TextField();
// Declare other components
public Address(Layout layout) {
this.layout = layout;
setCompositionRoot(layout);
}
}
layout.addComponent(ligne1);
// Add other components
public void setSpacing(boolean spacing) {…}
public boolean isSpacing() {…}
public String getLigne1Caption() {…}
// Other getters and setters
13. UI design vs data design
Address address = new Address();
address.getLigne1().setValue("M. Nicolas Frankel");
address.getLigne2().setValue("Route du Simplon 1");
address.getVille().setValue("Paudex");
address.getNpa().setValue("1094");
Tight coupling
No abstraction
No validation as a whole
No JSR-303
18. Composition summary
Think about UI configuration
Think about the wrapped model
Make it easy for your developers, they are your users
This makes it hard for you as the designer!
26. Shared state
Create API server-side
Create a getter/setter on the shared state
Implement onStateChanged() on the connector
Call widget’s methods accordingly
27. YouTubeState client-side
public class YouTubeState extends AbstractComponentState {
private String movieId;
public String getMovieId() {
}
return movieId;
public void setMovieId(String movieId) {
}
}
this.movieId = movieId;
28. YouTubePlayer server-side
public class YouTubePlayer extends AbstractComponent {
public YouTubePlayer(String movieId) {
}
getState().setMovieId(movieId);
@Override
public YouTubeState getState() {
}
}
return (YouTubeState ) super.getState();
29. YouTubeConnector client-side
@Connect(YouTubePlayer.class)
public class YouTubeConnector extends
AbstractComponentConnector {
// get & create widget as previously
public void onStateChanged(StateChangeEvent e) {
}
}
super.onStateChanged(e);
String movieId = getState().getMovieId();
getWidget().setMovieID(movieId);
33. Client compilation
Only a single GWT compiled package per WAR
Compile once in the final WAR whatever the number of
widgets
And be done with it!
34. GWT widget wrap summary
1. Create server-side component API
2. Then develop what is needed
Client-side widget (if necessary)
Connector
State
3. No need to package compiled-client code more than
once
36. Extensions
Extensions are a way to add client-side features to an
existing component
Examples:
Tooltip on labels
Icon on text fields
Caps lock warning on password fields
Etc.
41. Usage
TextField tf = new TextField("Name");
new Tooltip().extend(tf);
And that’s all!
But you need GWT skills...
Noticed the tooltip is static?
"<div class='c-tooltip'>Static tooltip</div>"
42. Client-side state extension
public class TooltipState extends SharedState {
private String tooltip;
public String getTooltip() {
}
return tooltip;
public void setTooltip (String tooltip) {
}
}
this.tooltip = tooltip;
43. Dynamic extension server-side
public class Tooltip extends AbstractExtension {
@Override
public TooltipState getState() {
}
return (TooltipState) super.getState();
public void extend(TextField tf, String tooltip) {
getState().setTooltip(tooltip);
}
}
super.extend(link);
44. Dynamic Extension client-side
@Connect(TooltipExtension.class)
public class TooltipConnector extends AbstractExtensionConnector {
@Override
public TooltipState getState() {
}
return (TooltipState) super.getState();
@Override
protected void extend(ServerConnector target) {
…
String text = getState().getTooltip();
}
}
tooltip.add(new HTML("<div class='c-tooltip'>" + text + "</div>"));
…
46. Extension summary
1. For added client-side capacity
2. Simple usage server-side
3. Requires GWT skills
4. State to the rescue
For runtime changes
48. JavaScript before 7
window.executeJavascript(String script)
“ Executes JavaScript in this window.
This method allows one to inject JavaScript from the server
to client. A client implementation is not required to
implement this functionality, but currently all web-based
clients do implement this.
Use of this method should be avoided and instead it is
recommended to create new widgets with GWT.”
49. JavaScript before 7
Not always feasible to wrap JavaScript in GWT
Not always available GWT skills
Not always possible to use JavaScript directly
Nor maintainable when it is
50. JavaScript in 7
To embed scripts client-side
1. JavaScript extension
To improve existing widgets
2. JavaScript component
To add
52. @JavaScript usage
On server-side JavaScript extension
Absolute resources
https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js
Local resources
bootstrap.js
bootstrap_connector.js
53. Calling JS function
callFunction("functionName", arguments)
Provides a way to call JavaScript scripts server-side
54. JavaScript extension server-side
@JavaScript({ "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js",
"bootstrap.js",
"bootstrap_connector.js" })
public class JsTooltipExtension extends AbstractJavaScriptExtension {
public void extend(TextField tf, String tooltip) {
super.extend(tf);
}
}
callFunction("attach", tooltip);
55. Binding with JavaScript
There’s no connector per se
As there’s no GWT widget
But we still need to bind betwen server and client
All local scripts have to be in the same package as the
extension
56. JavaScript extension client-side
window.package_JavascriptTooltipExtension = function() {
this.attach = function(options) {
var connectorId = this.getParentId();
var element = this.getElement(connectorId);
var tf = element.childNodes[0];
tf.rel = "tooltip";
tf.title = options[0];
}
}
$(tf).tooltip();
57. JavaScript and state
State as seen previously applies
com.vaadin.shared.ui.JavaScriptComponentState
On client-side
window.package_JavascriptExtension = function() {
this.onChange = function() {
this.getState() …
}
}
58. JavaScript component
Very alike to extension
But will create the HTML DIV
Hopefully… never played with it
60. Wrap JavaScript summary
When JavaScript is available
Just need a JS connector script
Pros
No need to use GWT
Can still be packaged as JARs
Cons
Loses all static typing