How to make only some columns editable in a Vaadin Grid?
Asked Answered
A

7

7

Vaadin Grid allows to be defined as editable with

grid.setEditorEnabled(true);

This makes all visible columns editable. However I don't want the user to edit an specific column, but seems like the editable is an all or nothing.

The next best solution I have found is to define an editor field with a disabled editor, which almost does the trick but the user is still able to select the text and move the cursor (but the field is not editable anymore).

Grid.Column nameColumn = grid.getColumn("fullName");
nameColumn.setHeaderCaption("Full Name");
nameColumn.setEditorField(getNoEditableTextField());

...

private Field<?> getNoEditableTextField() {
    TextField noEditableTextFiled = new TextField();
    noEditableTextFiled.setEnabled(false);
    return noEditableTextFiled;
}

I believe Label cannot be used because it's not a Field.

Is there a better option to achieve this?

edit: as aakath said, there is a way of achieving this not enabling the column to be edited, but in doing so the cell value disappears when you edit the row, which is not desirable.

Agglomerate answered 17/6, 2015 at 9:8 Comment(0)
A
3

my solution is below. i have just finished. it was not tested too much. but it may give you some ideas.

ati

  getColumn(columnName).setEditable(true).setEditorField(getNoEditableField(columnName));

...

private Field<?> getNoEditableField(final String columnName) {
    CustomField<Label> result = new CustomField() {
        @Override
        protected Component getContent() {
            Label result = (Label) super.getContent();
            Object editedItemId = getEditedItemId();
            String value = DEFAULT_VALUE;
            if (editedItemId != null) {
                value = CustomizableGrid.this.toString(getContainerDataSource().getItem(editedItemId).getItemProperty(columnName).getValue());
            }
            result.setValue(value);
            return result;
        }

        @Override
        protected Component initContent() {
            Label result = new Label(DEFAULT_VALUE, ContentMode.HTML);
            result.setDescription(getColumnDescription(columnName));
            result.setStyleName("immutablegridcellstyle");
            return result;
        }

        @Override
        public Class getType() {
            return Label.class;
        }
    };
    result.setConverter(new Converter<Label, Object>() {
    //converter for your data
    });

    return result;
}
Aldous answered 8/7, 2015 at 18:36 Comment(1)
It works! I had to pass the grid as parameter for the method to be able to get the row being edited, but the result is what I expected. The converter for my use case was Converter<Label,String> as the column was already a derived string from my beanAgglomerate
D
6

Did you try calling setEditable(false) method on the column? I believe it should make the field non-editable when the item editor is active.

grid.getColumn("fullName").setEditable(false);
Dubiety answered 18/6, 2015 at 5:4 Comment(1)
Tried this, and the column is no longer editable. However the column disappears when the editor is shown, which is not desirable.Agglomerate
A
3

my solution is below. i have just finished. it was not tested too much. but it may give you some ideas.

ati

  getColumn(columnName).setEditable(true).setEditorField(getNoEditableField(columnName));

...

private Field<?> getNoEditableField(final String columnName) {
    CustomField<Label> result = new CustomField() {
        @Override
        protected Component getContent() {
            Label result = (Label) super.getContent();
            Object editedItemId = getEditedItemId();
            String value = DEFAULT_VALUE;
            if (editedItemId != null) {
                value = CustomizableGrid.this.toString(getContainerDataSource().getItem(editedItemId).getItemProperty(columnName).getValue());
            }
            result.setValue(value);
            return result;
        }

        @Override
        protected Component initContent() {
            Label result = new Label(DEFAULT_VALUE, ContentMode.HTML);
            result.setDescription(getColumnDescription(columnName));
            result.setStyleName("immutablegridcellstyle");
            return result;
        }

        @Override
        public Class getType() {
            return Label.class;
        }
    };
    result.setConverter(new Converter<Label, Object>() {
    //converter for your data
    });

    return result;
}
Aldous answered 8/7, 2015 at 18:36 Comment(1)
It works! I had to pass the grid as parameter for the method to be able to get the row being edited, but the result is what I expected. The converter for my use case was Converter<Label,String> as the column was already a derived string from my beanAgglomerate
D
2

I had the same problem and didn't want that clicking on id column opens editor. I solved it with adding an ItemClickListener as below. It works fine for me.

grid.addItemClickListener((ItemClickListener<GridBean>) event -> grid.getEditor().setEnabled(!event.getColumn().getCaption().equals("Id")));

Also byc clicking on specific columns Grid is not editable any more.

Diamante answered 4/7, 2017 at 8:39 Comment(0)
C
1

There is one tricky way to do it! I've just found out it. So, first of all you need to use grid with container, instead of direct rows adding:

BeanItemContainer<MyBean> container = new BeanItemContainer<>(MyBean.class);
setContainerDataSource(container);

Then remove fields setters from MyBean, except setters for fields what you have to edit.

Carencarena answered 29/6, 2015 at 12:44 Comment(3)
I'm currently using a BeanItemContainer, the bean class doesn't have a setFullName() method, and yet it is not showing anything when editing the row.Agglomerate
so, have you achieved the desired?Carencarena
I'm not sure it is working, I didn't have a setter in the first place.Agglomerate
C
1

I think the same can be achieved by making the grid an editable one by grid.setEditorEnabled(true); and disabling editing option for other columns like grid.getColumn(columnName).setEditable(false);. But I am not sure of any demerits of this method. Any suggestion is always appreciated.

Caldera answered 13/10, 2016 at 11:34 Comment(0)
A
1

Its simple just go to Vaadin Documentation what did from it is below: you can see here I gave a specified column Name

grid = new Grid<>();
    lst = new ArrayList<>();
    provider = new ListDataProvider<>(lst);
    lst.add(new Company(1, "Java"));
    grid.setDataProvider(provider);
    grid.addColumn(Company::getSerialNo).setCaption("Sr.no");
    TextField tf = new TextField();

    grid.getEditor().setEnabled(true);

    HorizontalLayout hlyt = new HorizontalLayout();
    grid.addColumn(Company::getName).setEditorComponent(tf, Company::setName).setCaption("Name").setExpandRatio(2);

    hlyt.addComponent(grid);
Allsopp answered 21/9, 2017 at 8:0 Comment(0)
E
0

I use the following approach to get a read-only field, the trick is override the setEnabled method to get a disabled textfield. If you trace the source code in Vaadin Grid, no matter what field you pass to a Grid, it will always call the field.setEnabled(true).

myGrid.getColumn(propertyId).setEditorField(new ReadOnlyField());

And

public class ReadOnlyField extends TextField
{
    public ReadOnlyField()
    {
        super();
        this.setReadOnly(true);
    }

    @Override
    public void setEnabled(boolean enabled)
    {
        // always set to disabled state
        super.setEnabled(false);
    }
}
Emanate answered 15/12, 2015 at 5:36 Comment(2)
Interesting approach, will try this and let you knowAgglomerate
This "works" but the behavior is misleading. Editor shows with save and cancel buttons but nothing is editable.Nolanolan

© 2022 - 2024 — McMap. All rights reserved.