"Uncaught TypeError: $0 is null" when setting focus on TextField in Grid

I have a my own ComboBox-like field that consists of a TextField with an “open” icon in the suffix. When I use this in a Grid editor and the “open” event handler sets focus on the field I get this error.

I’ve created a test view. This works even worse than in my real app.Here it fails every time.
Am I doing something wrong?
Btw, It did not fail when I just did grid.setitems(row1, row2);

@Route(value="/test")
public class Test extends VerticalLayout {

    public static class Row {
        
        String firstName;
        String lastName;
        
        public String getFirstName() {
            return firstName;
        }
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
        public String getLastName() {
            return lastName;
        }
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
        
    }
    
    public static class MyField extends TextField {
        
        public MyField() {
            super();
            
            var icon = VaadinIcon.CHEVRON_DOWN_SMALL.create();
            setSuffixComponent(icon);
            
            icon.addClickListener(event -> MyField.this.focus());
            
        }
        
    }
    
    public Test() {
    
        var grid = new Grid<Row>();
        
        Binder<Row> binder = new Binder(Row.class);
        Editor<Row> editor = grid.getEditor();
        editor.setBinder(binder);
        
        grid.addColumn(row -> row.getFirstName())
            .setHeader("First name")
            .setEditorComponent(row -> {
                var field = new MyField();
                
                binder.bind(field, Row::getFirstName, Row::setFirstName);
                return field;
            });
    
        grid.addColumn(row -> row.getLastName())
            .setHeader("Last name")
            .setEditorComponent(row -> {
                var field = new MyField();
                binder.bind(field, Row::getLastName, Row::setLastName);
                return field;
            });
        
        var row1 = new Row();
        var row2 = new Row();
        var rows = List.of(row1, row2);
        var listDataProvider = new ListDataProvider<Row>(rows);
        
        grid.setItems(listDataProvider);
        
        add(grid);
        
        grid.getEditor().editItem(row1);

        grid.addItemClickListener(e -> {
            editor.editItem(e.getItem());
            Component editorComponent = e.getColumn().getEditorComponent();
            if (editorComponent instanceof Focusable) {
                ((Focusable) editorComponent).focus();
            }
        });
        
    }
    
}

You click listener propagates to grid, a new editor is created and the component don’t exist anymore on the client side when the JS focusing the DOM element is executed. The weird thing is that the JS is executed :exploding_head:

As the click listener API in Vaadin don’t support controlling propagation, I guess it is cleanest to add a check to your itemclicklistener if the edited item is already the one that was clicked and ignore in that case.

BTW. The “editorComponent” is not Focusable (a wrapper by Grid internals) so that is obsolete code…

Ah… I didn’t realize that the setEditorComponent lambda was called every time.
I assumed it would be called once for every row.
When I add a “cache” of fields to the test app, the current issue goes away.

I’ll take this information back to the real app and see if that solves everything.

Thanks :smiley:

Surely, the editorComponent is the Field, not the editor-row, so should be fine?
Those lines are also copied from the non-buffered example in How to enable inline editing in Vaadin Grid

I have one example of how to setup Grid using Editor and improve UX by couple of nice tricks. Naturally this is a bit opinion based.