Edit a single row in a table with a checkbox

Good morning to all,
I started from a few days to use Vaadin and I’m a beginner. Here’s my problem:
I can not make it editable a single record in a table. Basically I created a table from a datasource and I added this to a column containing a checkbox for each row. I wish that after selecting the checkbox corresponding record become editable.
I post the code:

public void enter(ViewChangeEvent event) {

       
        ContactDao dao = new ContactDao();
        SQLContainer contacts= dao.selectAllContcts(TestUI.getDb());
        final Table t = new Table("contacts");
        t.setContainerDataSource(contacts);
        t.setWidth("50%");
        t.setSelectable(true);
        t.setImmediate(true);

        
                
        t.addGeneratedColumn("edit",new CheckBoxColumnGenerator());
        t.setColumnHeaders(new String[] { "Id",
                "Name","Surname", "Number of telephone", "Edit"});
        
        t.setPageLength(5);        
        t.setColumnReorderingAllowed(true);
        

//        final CheckBox switchEditable = new CheckBox("Editable");
//        switchEditable.addValueChangeListener(
//                new Property.ValueChangeListener() {
//                    public void valueChange(ValueChangeEvent event) {
//                        t.setEditable(((Boolean)event.getProperty()
//                                .getValue()).booleanValue());
//                    }
//                });
//        switchEditable.setImmediate(true);
//        layout.addComponent(switchEditable);
    
        layout.addComponent(t);
        addComponent(layout);
        //        
    }

[code]
public class CheckBoxColumnGenerator implements ColumnGenerator {

@SuppressWarnings("rawtypes")
@Override
public Object generateCell(final Table source, final Object itemId, Object columnId) {
     Property prop = source.getItem(itemId).getItemProperty("edit"); 
     CheckBox c =new CheckBox(null, prop);
    
     return c;
}

}
[/code]In this way I built my table but I can not figure out how to make a single row editable.

Thank you in advance for your attention.

In Table, you can only set the entire table to be editable with setEditable(). However, you can implement row-based editing by having a TableFieldFactory that generates editable fields only for the selected row, or it generates read-only fields and you set the fields writable when a row is selected/clicked.

Grid, on the other hand, only supports row-based editing.

Thank you for your response. Meanwhile I solved this in this way :

@Override
    public void enter(ViewChangeEvent event) {

        ConctactDao dao = new ContattoDao();
        SQLContainer contacts= dao.selectAllContacts(TestUI.getDb());
        final Table t = new Table("contacts");
        t.setContainerDataSource(contacts);
        t.setWidth("50%");
        t.setSelectable(true);
        t.setImmediate(true);
        t.setEditable(true);
        
        t.setPageLength(5);        
        t.setColumnReorderingAllowed(true);
        
        t.setTableFieldFactory(new TableFieldFactory() {
            private static final long serialVersionUID = 1L;

            @Override
            public Field<?> createField(Container container, Object itemId, Object propertyId, Component uiContext) {
                if (itemId == t.getData()) {
                    return DefaultFieldFactory.get().createField(container, itemId, propertyId, uiContext);
                }
                return null;
            }
        });
        t.addGeneratedColumn("", new ColumnGenerator() {
            private static final long serialVersionUID = 1L;

            @Override
            public Object generateCell(Table source, final Object itemId, Object columnId) {
                Button button = new Button(itemId == t.getData() ? "Save" : "Edit");
                button.addClickListener(new ClickListener() {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void buttonClick(ClickEvent event) {
                        if (t.getData() == null) {
                        
                            // edit
                            t.setData(itemId);
                            t.refreshRowCache();
                        } else if (itemId == t.getData()) {
                            System.out.println(itemId.toString());
                            System.out.println(t.getData().toString());
                            // save
                            t.setData(null);
                            // ...
                            t.refreshRowCache();
                        }
                    }
                });
                return button;
            }
        });
                
        layout.addComponent(t);
        addComponent(layout);
        //        
    }

I do not know if in this way is correct , but it works . what do you think?

Mmm, yeah, that looks like one way to do it. Returning null in the field factory results in read-only text, so no need to return a read-only field there, as I suggested earlier. The Edit/Save button’s functionality also looks good. Using the component’s data field is a one way to communicate that sort of things, although it if course reserves it for that use; using a member variable is probably more type-safe way.

Ok.
Thanks again for your feedback.

I have another problem: I would like to perform an update query on my db when user click on Save button in table. To do this I tryed in such a way:

[code]
public void buttonClick(ClickEvent event) {
if (t.getData() == null) {

                        // edit
                        t.setData(itemId);
                        t.refreshRowCache();
                    } else if (itemId == t.getData()) {
                        System.out.println(itemId.toString());
                        System.out.println(t.getData().toString());
                        // save
                        ContattoDao dao = new ContattoDao();
                        
                        String idcontatto = t.getData().toString();
                        
                        @SuppressWarnings("unused")
                        boolean x = dao.updateContatto(TestUI.getDb(), 
                                t.getItem(itemId).getItemProperty("nome").getValue().toString(),
                                t.getItem(itemId).getItemProperty("cognome").getValue().toString(),
                                t.getItem(itemId).getItemProperty("numeroTelefono").getValue().toString(),
                                Integer.parseInt(idcontatto));
                        t.setData(null);
                        // ...
                        t.refreshRowCache();
                    }
                }
            });

[/code][code]
public boolean updateContact(DatabaseHelper db, String nome, String cognome, String numeroTelefono, int idcontatto){

    SQLContainer container = null;
    try {
        String queryUpdate = "UPDATE contatto SET nome= '"+nome+"', cognome='"+cognome+"',numeroTelefono='"+numeroTelefono+"' WHERE idcontatto ="+idcontatto+";";

        FreeformQuery query = new FreeformQuery(queryUpdate,  db.getConnectionPool(), "idcontatto");
        container = new SQLContainer(query);
    
    } catch (SQLException e) {
      
        e.printStackTrace();
    }
    
    return true;
    

}

[/code]but an exception is thrown. Why? The query is correct but container remains null.