Reputation: 339472
I have successfully got my first Vaadin 7 app up and running, as created for me by the Maven archetype. This template for the app shows the layout, its widgets, and the business logic for the widget (button being clicked), all defined within the MyUI
class.
Where do I go from here? Do I just keep adding stuff in that MyUI
or is there a better way to build out the pieces of my app?
Here is the Java source code of the MyUI
given to me by the Maven archetype.
package com.example.vaadinlayoutsexample;
import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
/**
* This UI is the application entry point. A UI may either represent a browser window
* (or tab) or some part of a html page where a Vaadin application is embedded.
* <p>
* The UI is initialized using {@link #init(VaadinRequest)}. This method is intended to be
* overridden to add component to the user interface and initialize non-component functionality.
*/
@Theme("mytheme")
@Widgetset("com.example.vaadinlayoutsexample.MyAppWidgetset")
public class MyUI extends UI {
@Override
protected void init(VaadinRequest vaadinRequest) {
final VerticalLayout layout = new VerticalLayout();
final TextField name = new TextField();
name.setCaption("Type your name here:");
Button button = new Button("Click Me");
button.addClickListener( e -> {
layout.addComponent(new Label("Thanks " + name.getValue()
+ ", it works!"));
});
layout.addComponents(name, button);
layout.setMargin(true);
layout.setSpacing(true);
setContent(layout);
}
@WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {
}
}
Screen shot of app running.
Upvotes: 0
Views: 149
Reputation: 2552
When your application starts having a lot more views, you should start using at least a Navigator
as well as a ViewProvider
. Both class are in the Vaadin framework.
The Navigator
object would be created in the MyUI
class. Each view implements the View
interface, for each view you can also have a presenter (though this is not a Vaadin concept).
A custom ViewChangeListener
as well as a NavigationStateManager
might also be of use.
See https://vaadin.com/docs/-/part/framework/advanced/advanced-navigator.html for more details. I also have made of "base app" which uses both the MVP and DAO pattern, you can check it out here: https://github.com/nyg/vaadin-app-base.
Upvotes: 5
Reputation: 339472
The app template is purposely kept brief to make it easy to read and comprehend for a newbie. All the “moving parts” of the user interface are gathered in that one class, MyUI
.
Adding more and more widgets and behavior to that MyUI
quickly becomes unwieldy. There are many approaches you can take to break out your app into various pieces, as Vaadin is quite flexible in this regard. I will describe my own approach.
In real work, I keep the MyUI
class as short as possible. As a subclass of UI
, the MyUI
represents the entire viewport of content displayed by either:
In other words, the UI
class is just a blank canvas that knows how to fit inside the host’s rectangular viewport. The job of the UI
is to mediate between the host viewport and the Vaadin content. Managing the details of that Vaadin content is better left to a separate object, defined as subclasses of Layout
. So the UI
code becomes simpler, just a matter of juggling one or more Layout
subclass objects.
For example, you might display a log-in Layout
. Then if the user authenticates successfully you switch out that Layout
. It its place you instantiate a different Layout
subclass to display your app’s main content. Your MyUI
code would handle the switching from a LoginLayout
layout object initially to replacement with a InvoiceListingLayout
layout object.
When starting a new Vaadin app, the first thing I do is extract the code for that VerticalLayout
and “Click Me” button, and move it to a new Java class file. The new class is an extension of VerticalLayout
, with a constructor that establishes the field, the button, and the behavior of the button.
Below is source code for that new class, ClickMeLayout
. Real-world layouts have much more code, so I usually break out that constructor method into three subroutines:
configure()
setSpacing
and setMargins
.widgets()
arrange()
I also made explicit the this.
syntax, my own preference.
Here is the new class, ClickMeLayout.java
.
package com.example.vaadinlayoutsexample;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
/**
*
* @author Basil Bourque. Use freely, but only at your own risk entirely.
*/
public class ClickMeLayout extends VerticalLayout {
private TextField name = null;
private Button button = null;
public ClickMeLayout () {
this.configure ();
this.widgets ();
this.arrange ();
}
private void configure () {
this.setMargin ( true );
this.setSpacing ( true );
}
private void widgets () {
// “Name” field
this.name = new TextField ();
this.name.setCaption ( "Type your name here:" );
// “Click Me” button
this.button = new Button ( "Click Me" );
this.button.addClickListener ( e -> {
this.addComponent ( new Label ( "Thanks " + this.name.getValue () + ", it works!" ) );
} );
}
private void arrange () {
this.addComponent ( this.name );
this.addComponent ( this.button );
}
}
With that class established, we can go back to shorten the MyUI
class. The MyUI::init
method shrinks to a single line of code.
@Override
protected void init ( VaadinRequest vaadinRequest ) {
this.setContent ( new ClickMeLayout () );
}
Make sure that all works. Do a clean-and-build in your IDE. Run the app to see if it works as it did originally.
Proceed to build your real app. Copy-paste that ClickMeLayout.java
code, create a new class, and paste to use as a prototype. Start adding widgets to build out your new Layout
. Go back to MyUI
to comment-out that one line with new ClickMeLayout()
, copy-paste that line to duplicate it, and alter the duplicate to call your new layout class instead of ClickMeLayout
.
@Override
protected void init ( VaadinRequest vaadinRequest ) {
// this.setContent ( new ClickMeLayout () );
this.setContent ( new InvoiceListingLayout () );
}
I suggest keeping the ClickMeLayout
around permanently in its original state. I find it to be a handy sanity-check. Eventually when your app seems to go haywire, you may not be sure if the problem is your own code or some glitch with your IDE, your web container (Tomcat, Jetty, etc.), your web browser, or who-knows-what. In that situation, you can go back to that MyUI
method, disable the call to your layout, re-enable the line calling new ClickMeLayout()
, do a clean-and-rebuild, and run the app. If that runs successfully, you know the fault lies within your code.
By the way, if that new lambda syntax seen in the addClickListener
line throws you off, here is the equivalent code using the old Java syntax as an anonymous inner class.
this.button.addClickListener ( new Button.ClickListener () {
@Override
public void buttonClick ( Button.ClickEvent e ) {
ClickMeLayout.this.addComponent ( new Label ( "Thanks" + ClickMeLayout.this.name.getValue () + ", it works!" ) );
}
} );
Upvotes: -1