How to make a pair of radio buttons in Vaadin 7 to represent True/False values but localized text?
Asked Answered
W

2

7

I want a pair of radio buttons in Vaadin 7 to represent boolean values where each value has a textual display such as "Active" and "Inactive".

screen shot of radio buttons "Active" and "Inactive" in group labeled "Filter By:".

Well answered 14/10, 2014 at 3:57 Comment(1)
Vaadin 8 update – Now much easier. See my Answer.Well
W
11

Vaadin 7

This Answer addresses Vaadin 7 as asked in the Question. Note that Vaadin 8 makes this much easier. See my other Answer.

OptionGroup Widget

In Vaadin 7, radio buttons are handled as a single widget, an instance of OptionGroup. The widget contains multiple Items, and if set to single item selection mode, they display as a group of radio buttons.

Item Id versus Item

The tricky part for me was understanding that the commands such as addItem are a bit of a misnomer. We do not pass full Item instances. Rather, we pass an object that is to serve as the id of the item.

The addItem command takes the item id, generates an Item instance and returns it to you. This is clearly documented, but took a while for me to sink in. You might think you are obligated to track that returned Item. But, no, you can use the item id to later retrieve or compare Items within the OptionGroup.

Since we need not track the returned Items, we can call the addItems (plural) command to use one line of code to create multiple items for multiple radio buttons.

Boolean As Item Id

In our case, we want to use boolean values as our core data. We need objects rather than boolean primitives because we are passing around objects. So we use the Boolean class. Notice that the Boolean class a couple of handy constants: Boolean.TRUE & Boolean.FALSE.

These Boolean objects can be used as the item ids.

Example Code

Some example code using Vaadin 7.3.2.

this.activeCustomerRadio = new OptionGroup( "Filter By:" );  // Pass a string used as caption (title) of the group of radio buttons.
this.activeCustomerRadio.addItems( Boolean.TRUE , Boolean.FALSE );  // Pass item ids to be used in constructing Item objects on our behalf.
this.activeCustomerRadio.setItemCaption( Boolean.TRUE , "Active" ); // Specify a textual label rather than default generated value "true" & "false".
this.activeCustomerRadio.setItemCaption( Boolean.FALSE , "Inactive" );
this.activeCustomerRadio.setValue( Boolean.FALSE );  // Specify which radio button is selected by default.
// Add a listener to react to user selection.
this.activeCustomerRadio.addValueChangeListener( new Property.ValueChangeListener()
{

    @Override
    public void valueChange ( Property.ValueChangeEvent event )
    {
        Notification.show( "Radio Button" ,
                "You chose: " + event.getProperty().getValue().toString() ,
                Notification.Type.HUMANIZED_MESSAGE );
    }
} );

Lambda Syntax

By the way… In Java 8, you can use the new alternate Lambda syntax. NetBeans 8 will suggest and perform the conversion to lambda syntax if you wish.

this.activeSupplierRadio.addValueChangeListener(( Property.ValueChangeEvent event ) -> {
    Notification.show( "Radio Button" ,
            "You chose: " + event.getProperty().getValue().toString() ,
            Notification.Type.HUMANIZED_MESSAGE );
});
Well answered 14/10, 2014 at 3:57 Comment(2)
Given that Boolean.true == true and that the compiler will auto box, can't you just pass true? What happens if you do?Haeckel
I'm in the pro-Object camp, wishing Java never had primitives. I suppose auto-boxing would work in this code. But I don't see the upside.Well
W
2

tl;dr

Much simpler in Vaadin 8.

radios.setItems( Boolean.TRUE , Boolean.FALSE );

…and…

radios.setItemCaptionGenerator( ( ItemCaptionGenerator < Boolean > ) item ->
{
    return item ? "Active" : "Inactive"; // Alternate labels.
} );

Vaadin 8

So much easier and more intuitive in Vaadin 8!

Vaadin 8 brings a new simplified data model, leveraging modern features of the Java language to eliminate the Container interface that wrapped your content in the old data model.

Support for Java Generics means the radio button widget knows the type of your content items. In the case of this Question, that type is the Boolean class.

RadioButtonGroup < Boolean > radios = new RadioButtonGroup <>( "T/F:" );

Pass objects to be represented by radio buttons

Now we just throw our objects at a widget such as RadioButtonGroup. In the case of this Question, we throw a pair of Boolean objects, the predefined constants Boolean.TRUE and Boolean.FALSE. Reverse the order of the arguments to change the order of the radio buttons presented to user.

radios.setItems( Boolean.TRUE , Boolean.FALSE );

To pre-select one of the radio buttons, just refer to the desired item object. Here that would be either constant, Boolean.TRUE or Boolean.FALSE.

radios.setValue( Boolean.FALSE );

As to the labels we present to the user for each radio button, by default each item object has its toString method invoked. For us here, that would mean true and false would be the text used for the radio button labels.

screen shot of radio buttons labeled "true" and "false"

Generating labels

Our Question here calls for alternate labeling of our radio buttons, such as for localization. So we call setItemCaptionGenerator and pass a little generator we write to generate a String for each radio button.

Our generator uses the ternary operator, handy for a conditional based on a boolean value. Remember that in the following code, a item is a Boolean object.

radios.setItemCaptionGenerator( new ItemCaptionGenerator < Boolean >( )
{
    @Override
    public String apply ( Boolean item )
    {
        return item ? "vrai" : "faux"; // French for "true"/"false".
    }
} );

Or use lambda syntax.

radios.setItemCaptionGenerator( ( ItemCaptionGenerator < Boolean > ) item ->
{
    return item ? "vrai" : "faux"; // French for "true"/"false".
} );

Here is a screen shot of the same Boolean objects being presented with labels in French.

screen shot of Vaadin radio buttons with labels in French "vrai" and "faux"

Specifically requested in the Question, "Active" & "Inactive".

radios.setItemCaptionGenerator( ( ItemCaptionGenerator < Boolean > ) item ->
{
    return item ? "Active" : "Inactive"; // Alternate labels.
} );

Respond to user

You may want to respond when the user wants to click a radio button. Add a value change listener. Notice how we are informed as to the object behind the item selected by the user, not the text of the label we generated. The call to event.getValue( ) returns the type Boolean without the need for casting because of Java Generics – The code here knows that the radio buttons represent Boolean objects, not mere text.

radios.addValueChangeListener( new HasValue.ValueChangeListener < Boolean >( )
{
    @Override
    public void valueChange ( HasValue.ValueChangeEvent < Boolean > event )
    {
        Notification.show(
                "User chose: " + event.getValue( ) ,
                Notification.Type.TRAY_NOTIFICATION
        );
    }
} );

Or use lambda syntax.

radios.addValueChangeListener( ( HasValue.ValueChangeListener < Boolean > ) event -> Notification.show(
        "User chose: " + event.getValue( ) ,
        Notification.Type.TRAY_NOTIFICATION
) );

screen shot of tray notification after user clicked a radio button

Entire example

Here is an entire working example, in a single class file.

package com.example.vaadin.radio;

import javax.servlet.annotation.WebServlet;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.data.HasValue;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.*;

/**
 * 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" )
public class MyUI extends UI
{

    @Override
    protected void init ( VaadinRequest vaadinRequest )
    {
        final VerticalLayout layout = new VerticalLayout( );

        RadioButtonGroup < Boolean > radios = new RadioButtonGroup <>( "T/F:" );
        radios.setItems( Boolean.TRUE , Boolean.FALSE );
        radios.setValue( Boolean.FALSE );
        radios.setItemCaptionGenerator( ( ItemCaptionGenerator < Boolean > ) item ->
        {
            return item ? "vrai" : "faux"; // French for "true"/"false".
        } );
        radios.addValueChangeListener( new HasValue.ValueChangeListener < Boolean >( )
        {
            @Override
            public void valueChange ( HasValue.ValueChangeEvent < Boolean > event )
            {
                Notification.show(
                        "User chose: " + event.getValue( ) ,
                        Notification.Type.TRAY_NOTIFICATION
                );
            }
        } );

        layout.addComponent( radios );
        setContent( layout );
    }

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

More info

See the manual for radio buttons.

See the radio button example in the Sampler.

See What's new in Vaadin.

Well answered 13/9, 2017 at 5:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.