Clickable Textfield?

Without creating a custom component, is there a way to add a click listener (Click or MouseEvent click) to a TextField?

Hi,

Vaadin supports listening click events from layouts, so you can do something like:

VerticalLayout layout = new VerticalLayout();

final TextField textField = new TextField();
layout.addComponent(textField);
layout.addListener(new LayoutClickListener() {

	public void layoutClick(LayoutClickEvent event) {
		if (event.getChildComponent() == textField) {
			System.out.println("clicked the TextField");
		}
	}
});

Note that TextField supports listening the focus and blur events. Depending on your needs, using these listeners might be enough.

-Henri

Is there a way to add the ClickListener and still be able to use the TextField as a Field returned by a FieldFactory?

Don’t see why not. Just add the layout click listener to the layout in the form you populate with the field factory. You can get the layout reference from the form with Form.getLayout() method.

What about for a Table?

Here’s what I’m trying to do. I want to have a TextField in a Table containing text from a Collection. If the user clicks on the TextField, I want to pop-up a window with a Table showing just the Collection.

I’ve figured out the ClickListener part, through using a CustomField. However, I can’t figure out how to get the Window to pop-up. My code looks like it should work but it just isn’t. Any help would be appreciated.


import java.util.Collection;
import java.util.Iterator;

import org.apache.commons.lang.StringUtils;

import com.vaadin.event.LayoutEvents.LayoutClickEvent;
import com.vaadin.event.LayoutEvents.LayoutClickListener;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomField;
import com.vaadin.ui.Label;
import com.vaadin.ui.ListSelect;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

/*
 * This button is intended to be a Field in a table or form to represent a Collection Property in an
 * Item. When the button is pressed, a window pops up displaying the Collection in list form.
 */
public class ListViewCustomTextField extends CustomField implements LayoutClickListener {

    private static final long serialVersionUID = 5105401230003639548L;
    private Collection<?> c;
    private TextField tf;
    private Window subwindow;

    public ListViewCustomTextField(final Collection<?> c) {
        super();
        this.c = c;

        final VerticalLayout layout = new VerticalLayout();
        tf = new TextField("", StringUtils.left(collectionToString(c), 10) + "...");
        // this is a view only Field
        tf.setEnabled(false);
        layout.addComponent(tf);
        layout.addListener(this);
        setCompositionRoot(layout);
    }

    @Override
    public void layoutClick(final LayoutClickEvent event) {

        final Component cc = event.getChildComponent();
        if (!cc.equals(tf)) {
            return;
        }

        subwindow = new Window("Item Viewer");
        // ...and make it modal
        subwindow.setModal(true);

        // Configure the windws layout; by default a VerticalLayout
        final VerticalLayout subWinLayout = (VerticalLayout) subwindow.getContent();
        subWinLayout.setMargin(true);
        subWinLayout.setSpacing(true);

        final Label message = new Label("This is a subwindow");
        subwindow.addComponent(message);

        // Add some content; a label and a close-button
        final Table display = new Table();
        display.setContainerDataSource(new ListSelect("", c));
        display.setEditable(false);
        subwindow.addComponent(display);

        final Button close = new Button("Close", new Button.ClickListener() {
            private static final long serialVersionUID = -2133615823981360079L;
            @Override
            public void buttonClick(final ClickEvent event) {
                if (subwindow.getParent() != null) {
                    // window is already showing
                    getWindow().showNotification("Window is already open");
                } else {
                    // Open the subwindow by adding it to the parent window
                    getWindow().addWindow(subwindow);
                }
            }
        });
        // The components added to the window are actually added to the window's
        // layout; you can use either. Alignments are set using the layout
        subWinLayout.addComponent(close);
        subWinLayout.setComponentAlignment(close, Alignment.TOP_RIGHT);
        getWindow().addWindow(subwindow);
        subwindow.bringToFront();
    }

    private String collectionToString(final Collection<?> coll) {
        String s = "";
        Object o = null;
        for (final Iterator<?> i = coll.iterator(); i.hasNext();) {
            if (!("".equals(s))) {
                s = s + ", ";
            }
            o = i.next();
            s = s + o.toString();
        }
        return s;
    }

    @Override
    public Class<?> getType() {
        return String.class;
    }

}

Got it working. Please ignore above. Was some combination of the table not actually getting populated and not properly sizing the window. This gets the job done:

    public void layoutClick(final LayoutClickEvent event) {

        final Component cc = event.getChildComponent();
        if (null == cc) {
            return;
        }
        if (!cc.equals(tf)) {
            return;
        }

        final Component display;
        display = new Table();
        ((AbstractSelect) display).setContainerDataSource(new ListSelect("", c));

        final Window cdd = new Window("View Table");
        cdd.setModal(true);
        ((VerticalLayout) cdd.getContent()).setSizeUndefined();
        cdd.addComponent(display);
        cdd.center();
        this.getWindow().addWindow(cdd);
        cdd.bringToFront();
    }