How to handle table navigation in editable mode in Vaadin?

Hi everyone, I have some troubles with the Table’s component. I an reading the book of Vaadin, at chapter 5.21.3 at “Navigation in Editable Mode”, there’s an example of a custom navigation handling, using custom Handler, here is the implementation:

public class KbdHandler implements Handler {




/**

     * 

     */

private static final long serialVersionUID = 1L;

    

Action tab_next = new ShortcutAction("Tab", 

                                         ShortcutAction.KeyCode.TAB, 

                                         null);

    Action tab_prev = new ShortcutAction("Shift+Tab", 

                                          ShortcutAction.KeyCode.TAB,

                                          new int[] {ShortcutAction.ModifierKey.SHIFT});

    Action cur_down = new ShortcutAction("Down",

                                         ShortcutAction.KeyCode.ARROW_DOWN, 

                                         null);

    Action cur_up   = new ShortcutAction("Up",

                                         ShortcutAction.KeyCode.ARROW_UP,   

                                         null);

    Action enter   = new ShortcutAction("Enter",

                                        ShortcutAction.KeyCode.ENTER,      

                                        null);




private Table table;

private HashMap<Integer, TextField> valueFields;

    

    public KbdHandler(Table table, HashMap<Integer, TextField> valueFields) {

        this.table = table;

        this.valueFields = valueFields;

    }

    

    @Override

    public Action[] getActions(Object target, Object sender) {

        return new Action[] {tab_next, tab_prev, cur_down,

                             cur_up, enter};

    }

    

@Override

public void handleAction(Action action, Object sender, Object target) {

        if (target instanceof TextField) {

            // Move according to keypress

            Integer itemId = (Integer) ((TextField)target).getData();

            if (action == tab_next || action == cur_down) {

                itemId++;

            }

            else if (action == tab_prev || action == cur_up) {

                itemId--;

            }

            // On enter, just stay where you were. If we did

            // not catch the enter action, the focus would be

            // moved to wrong place.

            

            if (itemId >= 0 && itemId < table.size()) {

                TextField newTf = valueFields.get(itemId);

                if (newTf != null) {

                    newTf.focus();

                }

            }

        }

        

    }




}

And the table inside init() UI’s method:

// Handling Table navigation in editable mode

        // Create a table. It is by default not editable.

        final Table tbl = new Table();

        tbl.setEditable(true);




        // Define the names and data types of columns.

        tbl.addContainerProperty("Date",     Date.class,  null);

        tbl.addContainerProperty("Work",     Boolean.class, null);

        tbl.addContainerProperty("Comments", String.class,  null);

        tbl.addContainerProperty("Numeric field", Integer.class, null);

        

        // Can't access the editable components from the table so

        // must store the information

        final HashMap<Integer,TextField> valueFields = new HashMap<Integer,TextField>();

        tbl.setTableFieldFactory(new TableFieldFactory() {

            

            @Override

            public Field<?> createField(Container container, Object itemId,

                    Object propertyId, Component uiContext) {

                TextField field = new TextField((String) propertyId);

                

                // User can only edit the "Numeric field"

                if (propertyId instanceof Integer) {

                    

                    field.setData(itemId);

                    

                    // Remeber the field

                    valueFields.put((Integer) itemId, field);

                    

                    // Focus if it is the first editable value

                    if ((Integer) itemId == 0) {

                        field.focus();

                    }

                }

                else {

                    field.setReadOnly(true);

                }

                return null;

            }

        }); 

        // Add a few items in the table.

        for (int i=0; i<100; i++) {

            Calendar calendar = new GregorianCalendar(2008,0,1);

            calendar.add(Calendar.DAY_OF_YEAR, i);

            

            // Create the table row.

            tbl.addItem(new Object[] {calendar.getTime(),

                                        new Boolean(false),

                                        "",

                                        i},

                          new Integer(i)); // Item identifier

        }

        

        tbl.setPageLength(8);

        tbl.setSizeFull();

        

        // Panel that handles keyboard navigation for the Table tbl

        Panel navigator = new Panel(tbl);

        navigator.addStyleName(Reindeer.PANEL_LIGHT);

        navigator.addActionHandler(new KbdHandler(tbl, valueFields));

        

        layout.addComponent(tbl);

        final CheckBox switchEditable = new CheckBox("Editable");

        switchEditable.setValue(true);

        switchEditable.addValueChangeListener(

            new Property.ValueChangeListener() {

                public void valueChange(ValueChangeEvent event) {

                    tbl.setEditable(((Boolean)event.getProperty().getValue()).booleanValue());

            }

        });

        switchEditable.setImmediate(true);

        layout.addComponent(switchEditable);

        

        // Handle the header clicks

        tbl.addHeaderClickListener(new Table.HeaderClickListener() {

            public void headerClick(HeaderClickEvent event) {

                String column = (String) event.getPropertyId();

                Notification.show("Clicked " + column +

                        "with " + event.getButtonName());

            }

        });

My problem is that the resulting table columns are
all

not editable
, but actually I would like to have the “Numeric Field” column editable. How can I accomplish this?

In the field factory, you are testing “propertyId instanceof Integer”. The property ID is an
identifier
, a string, not the property value object! The property IDs are strings in your code, such as “Numeric field” for the integer property. So, you should rather test using string comparison:

if ("Numeric field".equals(propertyId)) {

Note that you can also return a Label instead of a read-only TextField. Labels are simpler and therefore faster to render in the browser.

@Marko! Thank you so much, you save my week!!! Also I have found that inside the field factory I was returning
null
, but I needed to return the field.

Anyway, thank you for this helpful book and for your help!