Close

Vaadin Core Elements 2 Roadmap

Polymer 2 support, more components, and theming support

Vaadin Elements 2 Polymer 2 support

These are exciting times for Web developers. More and more browsers have shipped native support for Web Components, allowing us to rely less on polyfills and finally realize the full potential of Web Components. You might have seen that Google released a new Polymer-based version of Youtube a couple weeks ago. Several other large companies like General Electric and McDonald's have also showcased production applications built with Web Components. We're finally seeing Web Components move from "cool future technology" to something that's running business critical apps and sites for large companies.

Announcing Polymer 2 support

One of the major highlights of Google I/O 2017 is the release of Polymer 2.0. This new version of Polymer is both faster and more interoperable than before because it is able to use browser native Web Component implementations and new ECMAScript features.

Vaadin Elements is being updated to support Polymer 2.0, with the most elements already offering hybrid support (works both with Polymer 1 and 2). We are working to add support for the remaining components within the next few weeks. You can follow the implementation status on our GitHub repo or browse the components at vaadin.com/elements.

Looking ahead – building a cohesive, themeable set of components for the next generation of Web apps

While Web Components as a technology has matured, the ecosystem is still young. When it comes to cohesive component sets, Polymer's Paper Elements is still the gold standard. When we started building Vaadin Elements, we understood that it would take us some time to get a complete enough set of components to allow our users to build complete applications. That's why we designed the first iteration to work as an extension to the Polymer Paper Elements set.

One of the most common issues we hear from our users is that the Paper Element set and our components follow Material design and that they want their project to follow their own design. That's why we are evolving Vaadin Elements into a stand-alone set Web Components that you can easily theme to match the look and feel of your organization.

Vaadin Elements theming support

The theming support will allow you to easily customize the look and feel of all Vaadin Elements with CSS custom properties and standard CSS.

Roadmap

Building a new set of components is no small task, especially when you pay as much attention to detail, quality, and accessibility as we do. Getting the entire set of components completed will take some time. Our plan is to work from most commonly used components to more specific use case components. The goal is to have a set of components that is on par with and then going beyond the Vaadin Framework's current set of components. By starting with the most common components, we can cover the majority of use cases as soon as possible.

The roadmap below outlines our current priorities and schedule. We'll keep you updated on progress and show demos as soon as we have something that's ready enough for you to start trying out and giving feedback on.

May

  • vaadin-button
  • vaadin-text-field
  • vaadin-form layout

June – July

  • vaadin-list-box
  • vaadin-dialog
  • vaadin-dropdown-menu

August – October

  • Theming support for all components
  • vaadin-text-area
  • vaadin-checkbox

Later

  • vaadin-menu-button
  • vaadin-progress
  • vaadin-details
  • vaadin-radio-button
  • vaadin-slider
  • vaadin-spinner
  • vaadin-tabs
  • vaadin-tab
  • vaadin-toggle-button

What do you want to see next?

Although we have a clear vision of what we want to build next, we welcome all your comments and suggestions. Are there specific components or features you'd like us to add? Reach out to us on Twitter, Gitter for a chat, or file an issue on GitHub for enhancements you'd like to see.

Browse all Vaadin Elements

A Guide to migrating from GXT to Vaadin

Vaadin has always had a strong position when companies are evaluating the next platform to migrate their Java based desktop applications to. The programming model of Vaadin Framework is very similar to their existing codebase, which immediately makes Vaadin feel natural and productive to work with. The strong migration story continues even more so with GXT and other GWT based applications. In addition to the similar component based and event driven Java programming model, there is a distinctive advantage in migrating a GXT/GWT application to Vaadin. To highlight how straightforward the migration can be, I compiled a guide for migrating GXT (and GWT) based applications to Vaadin Framework called:  “7-step guide to migrating from GXT to Vaadin”.

The migration guide is based on a real customer case where our experts successfully migrated a fairly large GWT application to Vaadin. The guide describes the migration path, where you don’t have to rewrite your front-end completely right away, but instead you can keep most of your codebase as such. After the initial steps, you get your app running on Vaadin platform, and you gradually start working towards fully migrating to Vaadin Framework at your own pace. Any new development is done in Vaadin code, which allows you to keep delivering and releasing new features while migrating.

The migration guide contains practical steps for successful migration. The guide is available at https://vaadin.com/gxt. Go check it out.

How to bind your form to your domain model – the Vaadin 8 style

Lots of web applications require the user to input some data in order to manipulate it later. This article shows how Vaadin makes this task easy to implement.

We will be using Vaadin 8 and Java 8 in this article. The source code can be found at the following GitHub page: https://github.com/SomeoneToIgnore/vaadin-binders

To launch the example, you can use jetty plugin, clone the project and run the following command in project directory: mvn jetty:run

Basic example

This is how the basics work. Let's create a form that allows the user to generate an image, basing on user input:

public class BinderUI extends UI {
    private final TextField text = new TextField();
    private final TextField imageSize = new TextField();

    @Override
    protected void init(VaadinRequest vaadinRequest) {
        setContent(new VerticalLayout(text, imageSize));
    }
}

Now, let's define a corresponding class that will be responsible for storing the form input:

public class ImageData {
    private String text;
    private int size;

    public ImageData(String text, int size) {
        this.text = text;
        this.size = size;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }
}

Later on, we will address this class as data class and its instances as data objects.

And the last thing left to do: the actual binding. For this action, we will need the Binder class from Vaadin framework. Let's append the following lines to init method:

Binder binder = new Binder<>();
// a shorthand method, if no extra configuration can be done
binder.bind(imageText, ImageData::getText, ImageData::setText);
// long way of binding, usually used for more complex bindings
binder.forField(imageSize).bind(
        imageData -> Integer.toString(imageData.getSize()),
        (imageData, formValue) -> imageData.setSize(Integer.valueOf(formValue))
);

That's it, now we have bound the data class to the form's contents.

A few explanations of the api:

  • There are two ways of binding to a field: binder.forField and binder.bind.

  • In current examples, both of them do the very same thing: establish the binding between the form field and the data object field.

    • binder.forField can be used for more complex bindings, involving validation and conversions. They will be described in later sections.

    • binder.bind form is just a shorthand, for cases when no validation or conversions are needed.

  • Both ways need four things to be declared:

    • type of the data object that will be bound: Binder<ImageData>

    • what field of the form to bind to: imageText and imageSize in this case

    • how to get data for form field from object: ImageData::getText and imageData -> Integer.toString(imageData.getSize())

    • how to set data from form field to object: ImageData::setText and (imageData, formValue) -> imageData.setSize(Integer.valueOf(formValue))

After the binding is done, let's explore the possibilities it gives to us.

Loading bound data

After binding is defined, we can use it to load the actual data into the form.

Vaadin provides the following api:

binder.setBean(imageData);

The setBean method first writes data object fields into the form fields and then tracks form fields' changes to update the object.

If we add this string to code above and start the application, we will see that our form is no more empty:

Now, whenever user changes the form contents, those changes will be written into corresponding objects using methods, specified in the binding.

The only exception for this case is a situation, when validation errors occur: if there are any, the bound object will not be changed. Validation will be described in later sections.

It is also important to notice that any consequent changes to a data object's state won't change the form.

ImageData imageData = new ImageData("Lorem ipsum", 20);
binder.setBean(imageData);
// the form will display Lorem ipsum still 
imageData.setText("Test test");
// the form will display 20 still
imageData.setSize(300);

In order to turn the automatic update off, we need to call either binder.removeBean() or binder.setBean(null). The latter method also clears form contents.

Validating user input

Let's have a look at the current state of the imageSize field binding:

binder.forField(imageSize).bind(
        imageData -> Integer.toString(imageData.getSize()),
        (imageData, formValue) -> imageData.setSize(Integer.valueOf(formValue))
);

bound form element is a TextField:

TextField imageSize = new TextField();

that accepts all kinds of characters, not only numeric. Non-numeric character input will cause obvious NumberFormatException because of the Integer.valueOf(formValue) binder setter expression.

In order to handle incorrect user input in a more convenient way, validators are used. Let's define the requirements for user input:

  • input should not be null or empty

  • input string should be a positive integer

This can be achieved by using the following api:

binder.forField(imageSize)
    .withValidator(string -> string != null && !string.isEmpty(), "Input values should not be empty")
    .withValidator(inputString -> {
        try {
            return Integer.valueOf(inputString) > 0;
        } catch (NumberFormatException ignored) {
            return false;
        }
    }, "Input value should be a positive integer")
    .bind(
            imageData -> Integer.toString(imageData.getSize()),
            (imageData, formValue) -> imageData.setSize(Integer.valueOf(formValue))
    );

Now, whenever the user inputs a string, a validation occurs, applying validators in order to be specified in the code, when updating the form and vice versa, when updating the object.

Let's see what we can do to improve the existing example.

Converting user input

Sometimes it is better to represent some data in a different way, not as an input text field. In those situations, the converters can help a lot.

By introducing a converter, we can reduce the number of string to integer conversions:

binder.forField(imageSize)
    .withValidator(string -> string != null && !string.isEmpty(), "Input values should not be empty")
    .withConverter(Integer::valueOf, String::valueOf, "Input value should be an integer")
    .withValidator(integer -> integer > 0, "Input value should be a positive integer")
    .bind(ImageData::getSize, ImageData::setSize);

It is also important to notice that Vaadin has numerous useful converters that may come in handy. For instance, it has a String to Integer converter that allows us to replace the previous example with

binder.forField(imageSize)
    .withValidator(string -> string != null && !string.isEmpty(), "Input values should not be empty")
    .withConverter(new StringToIntegerConverter("Input value should be an integer"))
    .withValidator(integer -> integer > 0, "Input value should be a positive integer")
    .bind(ImageData::getSize, ImageData::setSize);

As with validators, multiple converters can be added, both validators and converters are executed in order to be added in the code, when updating the form and vice versa, when updating the object.

You may have noticed that StringToIntegerConverter allows us to specify a validation error message. This shows one important feature of converters and validators: if any kind of exception occurs inside a validator or converter, a ValidationException is thrown. This allows Vaadin framework to handle exceptions properly, without propagating them to upper levels of the application.

But, if an exception occurs during conversions made in lambdas, for instance, like these:

binder.forField(imageSize).bind(
        imageData -> Integer.toString(imageData.getSize()),
        (imageData, formValue) -> imageData.setSize(Integer.valueOf(formValue))
);

the RuntimeException will be thrown and it will not be handled normally, as ValidationException. That's why converting values via withConverter is more preferable.

Subscribe to form fields' value changes

Every time the user updates the form, an event is fired if a binder was attached to the form. We can process these events in order to react to them:

binder.addStatusChangeListener(e -> {
    System.out.println("Change introduced validation errors: " + e.hasValidationErrors());
    System.out.println("Form was changed" + e.getBinder().hasChanges());
});

Be aware, that if hasValidationErrors method returns false, this only means that the change that triggered the event did not introduce any new validation errors: other errors may still be present in the form, making it invalid.

To check if form is valid, we can use the following handy method: e.getBinder().isValid().

Advanced binding

Sometimes, automatic bean update via binder.setBean is not convenient. Vaadin framework provides an alternative api for those cases.

Load data from data objects to form

In order to update form contents only once, readBean method can be used.

ImageData imageData = new ImageData("Lorem ipsum", 20);
binder.readBean(imageData);

This method can be also used to clean bean all form fields:

binder.readBean(null);

Note that this call modifies the corresponding data object, a null will be set to all the data object's properties, whenever possible, propagating ValidationException in other cases.

Load data from form to data object

Of course, the opposite operation is possible too, to write data from form input to object without subscribing to any form changes. Use the following code:

try {
    binder.writeBean(imageData);
} catch (ValidationException e) {
    // do something with the exception
    e.printStackTrace();
}

Another way is to check the return value:

boolean saved = binder.writeBeanIfValid(imageData);
if (saved) {
    // do something
} else {
    // do something else
}

Declarative binding

When there are many fields in form and model, it gets cumbersome to define every binding manually. To eliminate unnecessary boilerplate code, bindInstanceFields method can be used.

In order to bind properties declaratively, we should have an object with fields we want to bind. As you may see from the bindInstanceFields method signature, the type of the object does not matter. In our case, BinderUI has two fields defined, both of them are used in the same binding:

public class BinderUI extends UI {
    private final TextField text = new TextField();
    private final TextField imageSize = new TextField();

    // ... rest of the file goes here
 }

That's exactly what we need, so, we can put the

binder.bindInstanceFields(this);
line right after the last validator usage in the init method of BinderUI class.

 

We've specified the form elements that are used in the binding, so what about data class for them? A special constructor is used in this case,

Binder binder = new Binder<>(ImageData.class);
that defines the class that would be used as data class.

 

These two actions automatically set a relation between ImageData class' fields and two text fields, defined in BinderUI. For every text field in a form, the binder will try to find a property with the same name and corresponding type (String for TextField).

Let's remember the data object field structure:

public class ImageData {
    private String text;
    private int size;

    // ... rest of the file goes here
 }

It is clear that TextField text is automatically bound to String text field which means that the line binder.bind(imageText, ImageData::getText, ImageData::setText); is obsolete and we can get rid of it.

The other form field, TextField imageSize does not match the second field from data object, int size. We can fix this issue, by adding implicit mapping and implicit data conversion.

Implicit mapping is set via @PropertyId annotation set on form fields. It allows to specify a different name for a data object field that would be mapped to a corresponding form field.

// It is explicitly stated, that this field is mapped to a property with name `size`
@PropertyId("size")
private final TextField imageSize = new TextField();

A few words about the limitations:

  • No binding will be set if the class and form field’s names won't match.

  • If names match, but types do not, the framework will throw an exception.

What about conversion? Good news: all validations and conversions work in declarative bindings just as fine as in regular ones. We've already taken care of it, using StringToIntegerConverter in one of the bindings, so the only thing to keep in mind is to put binder.bindInstanceFields(this); after binding with conversion is defined.

One last thing to notice: when using the binder.bindInstanceFields, we can use binder.forMemberField instead of the binder.forField which allows to omit the bind call for every field pair that has the same names or annotated with the @PropertyId.

Putting it all together

This article showed lots of things that are possible with Vaadin Framework.

  • We can bind any java class to the form input fields

  • We can customize binding by adding validators and converters

  • We can update bound objects and form fields, either automatically or manually

  • We can track user input, validate it and react accordingly

  • We can bind forms and data objects fast and easy with declarative binding

 

Let's put all the gathered knowledge together in a final version of the example.

The ImageData class was not changed since its last appearance.

As for the BinderUI, the simple implementation can be represented with the following class:

public class BinderUI extends UI {
    // Field that would be used by binder.bindInstanceFields
    private final TextField text = new TextField();

    // Field that would be used by binder.bindInstanceFields
    // It is explicitly stated, that this field is mapped to a property with name `size`
    @PropertyId("size")
    private final TextField imageSize = new TextField();

    @Override
    protected void init(VaadinRequest vaadinRequest) {
        // crate a binder for a form, specifying the data class that will be used in binding
        Binder binder = new Binder<>(ImageData.class);

        // specify explicit binding in order to add validation and converters
        binder.forMemberField(imageSize)
                // input should not be null or empty
                .withValidator(string -> string != null && !string.isEmpty(), "Input values should not be empty")
                // convert String to Integer, throw ValidationException if String is in incorrect format
                .withConverter(new StringToIntegerConverter("Input value should be an integer"))
                // validate converted integer: it should be positive
                .withValidator(integer -> integer > 0, "Input value should be a positive integer");

        // tell binder to bind use all fields from the current class, but considering already existing bindings
        binder.bindInstanceFields(this);

        // crate data object with predefined imageName and imageSize
        ImageData imageData = new ImageData("Lorem ipsum", 2);

        // fill form with predefined data from data object and
        // make binder to automatically update the object from the form, if no validation errors are present
        binder.setBean(imageData);

        binder.addStatusChangeListener(e -> {
            // the real image drawing will not be considered in this article

            if (e.hasValidationErrors() || !e.getBinder().isValid()) {
                Notification.show("Form contains validation errors, no image will be drawn");
            } else {
                Notification.show(String.format("I will draw image with \"%s\" text and width %d\n",
                        imageData.getText(), imageData.getSize()));
            }
        });

        // add a form to layout
        setContent(new VerticalLayout(text, imageSize));
    }

    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
    @VaadinServletConfiguration(ui = BinderUI.class, productionMode = false)
    public static class MyUIServlet extends VaadinServlet {
    }
}

That's it for this time, for more detailed information, please refer to the documentation

Check out the full example project here