How to dynamically change the style for a TextField that is inside a Table?

I created a TextField inside a Table cell by a ColumnGenerator. After the TextField is created I cannot dynamically change its style via addStyleName(). The style I set is just ignored and not shown in the DOM representation of the resulting page.
Is this a problem of the table-rendering? I am using Vaadin 7.3.6

textField.addStyleName("modified")

styles.css:
.v-textfield-modified {
    background: #F2F5A9;
}

hi, try to climb up a little bit in DOM hierarchy like that :
td.v-table-cell-content div.v-table-cell-wrapper input.v-textfield-it-125{
background: green;
}
and don’t forget to clear browser data each time, it’s important when work with css
p.s. it’s a little bit strange why you use ColumnGenerator for TextField, btw hope this help

You need to call
refreshRowCache()
on the table, after adding/removing style name to the field.

Unfortunately, both hints don’t work. After the onSave() Method is processed, the style change seems lost.
When adding a style to a textField outside the table everything works fine!
refreshRowCache() has no effect on the styles.

textField.addValueChangeListener(e -> onSave(e));

private void onSave(final ValueChangeEvent event) {
  Event e = (Event) event;
  TextField textField = (TextField) e.getComponent();
  textField.addStyle("modified");
}

Don’t you do it in field factory?

table.setTableFieldFactory(new DefaultFieldFactory(){
            @Override
            public Field<?> createField(Container container, final Object itemId,
                    final Object propertyId, final Component uiContext) {
                final Field<?> textField= super.createField(container, itemId, propertyId, uiContext);
                textField.addValueChangeListener(e -> {
                    textField.addStyle("modified");
                    ((Table)uiContext).refreshRowCache();
                });
                return textField;
            }
});

Hello Agata. I am not familiar with FieldFactory’s. But from my understanding of the code it’s exactly the same like I do with the ColumnGenerator. At least in the ValueChangeEvent. I tried your code and ended up in an infinite loop though…
Did you succeed in updating the style?

        BeanItemContainer<MyBean> beanItemContainer = new BeanItemContainer<MyBean>(MyBean.class, new ArrayList<MyBean>());
        table.setContainerDataSource(beanItemContainer);
        table.setEditable(true);
        
        table.setTableFieldFactory(new DefaultFieldFactory() {
            @Override
            public Field<?> createField(final Container container, final Object itemId,
                final Object propertyId, final com.vaadin.ui.Component uiContext) {
                final Field<?> textField = super.createField(container, itemId, propertyId, uiContext);
                System.out.println("Infinite loop here");
                textField.addValueChangeListener(e -> {
                    textField.addStyleName("modified");
                    ((Table) uiContext).refreshRowCache();
                });
                textField.setEnabled(true);
                return textField;
            }
        });

Hi Dennis, this is my working code (with field factory and cell style generator :-)):

[code]
select.setEditable(true);
select.setTableFieldFactory(new DefaultFieldFactory(){
@Override
public Field<?> createField(Container container, final Object itemId, final Object propertyId, Component uiContext) { final Field<?> field = super.createField(container, itemId, propertyId, uiContext);
((AbstractTextField) field).addTextChangeListener(new TextChangeListener() {

                @Override
                public void textChange(TextChangeEvent event) {
                    edited.add(itemId);
                    saveButton.setEnabled(true);
                    revertButton.setEnabled(true);
                }
            });
            field.addValueChangeListener(new ValueChangeListener() {
                
                @Override
                public void valueChange(ValueChangeEvent event) {
                    if (!field.isModified()) {
                        return;
                    }
                    if (!field.isValid()){
                        field.addStyleName("red-background");
                        return;
                    }
                    field.removeStyleName("red-background");
                    try {
                        //some internal job here
                        field.commit();
                        select.refreshRowCache();
                    } catch (SQLException e) {
                        //error handling
                    }
                }
            });
            ((AbstractField<?>) field).setImmediate(true);
            field.setBuffered(true);
            field.setSizeFull();
            return field;
        }
    });
    select.setColumnExpandRatio("text", 1);
    select.setColumnExpandRatio("textA", 1);
    select.setSizeFull();
    select.setCellStyleGenerator(new CellStyleGenerator() {
        
        @Override
        public String getStyle(com.vaadin.ui.Table source, Object itemId,
                Object propertyId) {
            if (edited.contains(itemId)) {
                return "edited";
            }
            return null;
        }
    });

[/code]and

private Set<Object> edited;

Probably

if (!field.isModified()) { return; } prevents infinite loop (I’m not sure as the code is pretty old), but to get it work, the field must be set as buffered.

Hi Agata. Your example only works, because you are either doing a style change

field.addStyleName("red-background");
                            return;

or commiting the changes to the bean.

field.commit();

But I need both, doing the style change and the commit. When I commit, the style change is lost again (no matter if I commit before or after the style change). Do you have any ideas?

When the field value is changed form invalid to valid I do both (I believe it doesn’t matter if I’m adding or removing a style):

field.removeStyleName("red-background"); try { //some internal job here field.commit(); select.refreshRowCache(); } catch (SQLException e) { //error handling } and it works properly.

Ps. snippet from
mytheme.scss
:

.red-background { background: #FF6666; } So your style should probably be:

.modified {
    background: #F2F5A9;
}

I did some further tests and found out, that the commit() always resets the style to the initial style.
Adding or removing a style + commit() has no effect on the style.
In your code it seems like

field.removeStyleName("red-background");

is working, because the textField initially has no style “red-background”.
Is this behaviour intended? By the way, thank you very much for your quick responses!! :slight_smile:

Maybe it would be worth to report it as a bug.

Thanks, I did so: http://dev.vaadin.com/ticket/15403

I found out, that it’s not a defect. My ColumnGenerator repainted the cell after commit(), so the style changes were lost… :-S