Grid Connector issue when using TextField as an EditorField

As we begin to see a light at the end of the tunnel for our Grid development, a few minor issues remain. This particular issue isn’t critical, but it is visible so I would really love to get it resolved.

The issue is that when we leave the Editor Mode in the grid, we get the following warning:

Sep 14, 2015 11:27:37 AM com.vaadin.event.ConnectorActionManager handleAction
WARNING: Ignoring action for disabled connector com.vaadin.ui.TextField

While I understand this is just a warning, I like to have clean code so if I could resolve this warning I would be a much happier person.

So, what are we doing? Our Grid has the potential for 4 editable fields. The warning above fires once for each editable field. We are using TextFields for our EditorField in the Grid for two reasons, first to select the entire contents of the field when the field goes into editor mode, and second to add a ShortcutListener to handle the EnterKey properly. If we can get this functionality without using the TextField, problem solved. However, we couldn’t figure out how to do this, so this is the option we chose.

Now, I have a feeling that this problem may be caused by the way in which we are attaching the TextFields to the grid. Would couldn’t figure out how to get it to work, until we tried getting these fields to bind in the SelectionListener. Hence, our Grid’s selection listener looks like this:

        myGrid.addSelectionListener(new SelectionEvent.SelectionListener() {
            @Override
            public void select(SelectionEvent selectionEvent) {

                myGrid.getColumn("tna").setEditorField(tnaEditField);
                myGrid.getColumn("nav").setEditorField(navEditField);
                myGrid.getColumn("shares").setEditorField(sharesEditField);

            }
        });

Maybe we need to bind them elsewhere? Maybe we need to unbind them somewhere? Any thoughts or ideas would be most appreciated. Thanks.

You should just bind them once when you create the Grid and add the Columns. Think of the setEditorField() method like the setRenderer, the setHeaderCaption or the setConverter method. You define the Textfield as the Editor Field for every row in this column as you can only have one editor open at the same time.

Hi,

Are some of those editor fields sometimes disabled? If so, could you consider changing read-only status instead of the enabled status? It seems that the editor attempts to make some actions on the widgets and/or connectors on close and the warning is just a note that since it’s disabled, it doesn’t actually do anything.

Also the editor should update the fields as needed so only setting the fields once, and modifying them afterwards should be enough.

//Teemu

@marius. That’s what I initially thought as well, however if I bind it in the constructor, the entire application crashes on initialization. I tried it in various places, but it would only work in the selection listener. At the time, I assumed this was how it was meant to be done, so I moved on. In hindsight, it seems that I probably needed to take a different approach.

@teemu. I don’t use Enable/Disable or the read only flag. Instead, some columns have their editable field set based on various conditions within the screen. The code looks like this:

myGrid.getColumn("tna").setEditable(true);

… also @teemu, are you of the same opinion as Marius? Where should I be setting my renderer? I tried putting it at the tail end of my constructor, but this just locks makes my GUI more or less useless. It doesn’t crash (no exceptions or anything), but none of the screen widgets work … very strange behavior.

What do you mean it crashed and what do you mean by constructur?
The most simple code example for adding a custom Editor Field to a Grid is this:

[code]
VerticalLayout layout = new VerticalLayout(); //This code could be e.g. in UI.init
setContent(layout);

    IndexedContainer cont = new IndexedContainer();
    cont.addContainerProperty("A", String.class, "Test");
    cont.addContainerProperty("B", String.class, "AlsoTest");
    cont.addItem(); cont.addItem();
    
    Grid grid = new Grid(cont);
    grid.setEditorEnabled(true);
    
    PasswordField txt = new PasswordField();
    grid.getColumn("A").setEditorField(txt);
    
    layout.addComponent(grid);

[/code]If not even this is working i’m starting to get the feeling that something is screwed up in your environment as it seem to have problems with even simple code examples like e.g. my TextFieldRenderer that you couldn’t get to work.

I also get the impression that our environments are very different. I don’t know what environments you guys run on, but for development we are using IntelliJ with Jetty, and we deploy to Tomcat. Also, we develop in Windows but deploy to Solaris. Our database is Sybase 16, but I don’t think this has much to do with anything. What environment are you guys working in?

As for the code, our Grid setup is a bit different. Instead of a IndexedContainer we use a BeanItemContainer, but otherwise it is pretty close. Here is a rundown of our Grid Setup in our Panel. Oh, and by the constructor I mean the Panel’s actual constructor. Here’s a trimmed version (there’s a lot going on in there):

As you can see, we are binding the EditorField in the selection listener. However, if I bind it outside that listener, the application more or less stops working. Its hard to explain what that means because of the nature of the application, but one way to describe it is that there are three things that need to happen before the Grid can be populated, but if bind the EditorField in the way you describe, the first thing that needs to happen doesn’t work at all and nothing can happen after which will eventually populate the grid. I haven’t tried debugging this because I wasn’t sure how it was supposed to work in the first place. Now that I know, I will look into this from a different angle.

Oh, and regardign that TextFieldRenderer you suggested earlier, it never worked. I tried it in a sandbox environment on a different machine and it didn’t work there either … what environment do you guys work in?

@Inject
public ComplexGridModule(final WeeklyDAO dao) {

...
...

    complexes = new ArrayList<>();

    complexGrid.setContainerDataSource(new BeanItemContainer<>(ComplexModuleData.class));
    complexGrid.setColumnOrder("ct", "fundid", "ticker", "fundname", "tna", "tnac", "nav", "navc", "shares", "sharesc", "nncf");
    complexGrid.getColumn("ct").setHeaderCaption("#");
    complexGrid.getColumn("ct").setRenderer(new NumberRenderer(new DecimalFormat("#")));
    complexGrid.getColumn("fundid").setHeaderCaption("Fund ID");
    complexGrid.getColumn("fundid").setRenderer(new NumberRenderer(new DecimalFormat("#")));
    complexGrid.getColumn("ticker").setHeaderCaption("Ticker");
    complexGrid.getColumn("fundname").setHeaderCaption("Fund Name");
    complexGrid.getColumn("tna").setHeaderCaption("TNA");
    complexGrid.getColumn("tnac").setHeaderCaption("TC");
    complexGrid.getColumn("nav").setHeaderCaption("NAV");
    complexGrid.getColumn("navc").setHeaderCaption("NC");
    complexGrid.getColumn("shares").setHeaderCaption("Shares");
    complexGrid.getColumn("sharesc").setHeaderCaption("SC");
    complexGrid.getColumn("nncf").setHeaderCaption("NNCF");

    complexGrid.getColumn("ct").setEditable(false);
    complexGrid.getColumn("fundid").setEditable(false);
    complexGrid.getColumn("ticker").setEditable(false);
    complexGrid.getColumn("fundname").setEditable(false);
    complexGrid.getColumn("tna").setEditable(true);
    complexGrid.getColumn("nav").setEditable(true);
    complexGrid.getColumn("shares").setEditable(false);
    complexGrid.getColumn("tnac").setEditable(false);
    complexGrid.getColumn("navc").setEditable(false);
    complexGrid.getColumn("sharesc").setEditable(false);

    complexGrid.getColumn("ct").setWidth(60);
    complexGrid.getColumn("fundid").setWidth(75);
    complexGrid.getColumn("ticker").setWidth(100);
    complexGrid.getColumn("fundname").setWidth(385);
    complexGrid.getColumn("tna").setWidth(140);
    complexGrid.getColumn("tnac").setWidth(40);
    complexGrid.getColumn("nav").setWidth(140);
    complexGrid.getColumn("navc").setWidth(40);
    complexGrid.getColumn("shares").setWidth(140);
    complexGrid.getColumn("sharesc").setWidth(40);
    complexGrid.getColumn("nncf").setWidth(140);

    complexGrid.removeColumn("tnaold");
    complexGrid.removeColumn("navold");
    complexGrid.removeColumn("sharesold");
    complexGrid.removeColumn("tnaOrig");
    complexGrid.removeColumn("navOrig");
    complexGrid.removeColumn("sharesOrig");
    complexGrid.removeColumn("tnaDescription");
    complexGrid.removeColumn("navDescription");
    complexGrid.removeColumn("sharesDescription");
    complexGrid.removeColumn("classtype");
    complexGrid.removeColumn("iob");
    complexGrid.removeColumn("fof");
    complexGrid.removeColumn("tna_source");
    complexGrid.removeColumn("tna_entry_user");
    complexGrid.removeColumn("tna_entry_date");
    complexGrid.removeColumn("tna_update_user");
    complexGrid.removeColumn("tna_update_date");
    complexGrid.removeColumn("nav_source");
    complexGrid.removeColumn("nav_entry_user");
    complexGrid.removeColumn("nav_entry_date");
    complexGrid.removeColumn("nav_update_user");
    complexGrid.removeColumn("nav_update_date");
    complexGrid.removeColumn("shares_source");
    complexGrid.removeColumn("shares_entry_user");
    complexGrid.removeColumn("shares_entry_date");
    complexGrid.removeColumn("shares_update_user");
    complexGrid.removeColumn("shares_update_date");

    complexGrid.setSelectionMode(Grid.SelectionMode.SINGLE);
    complexGrid.setImmediate(true);
    complexGrid.setEditorEnabled(true);
    complexGrid.setEditorBuffered(false);

    complexGrid.setWidth("1180px");
    complexGrid.setHeightByRows(11);

    /* ---------------- GRID COLUMN TNA ------------------------ */

    TextField tnaEditField = new TextField();

    tnaEditField.setNullRepresentation("");

    tnaEditField.addFocusListener(new FieldEvents.FocusListener() {
        @Override
        public void focus(FieldEvents.FocusEvent event) {
            tnaEditField.selectAll();
        }
    });

    tnaEditField.addShortcutListener(
            new AbstractField.FocusShortcut(tnaEditField, ShortcutAction.KeyCode.ENTER, null) {

                @Override
                public void handleAction(Object sender, Object target) {

                    if (target == null) {
                        return;
                    }

                    Object targetParent = ((AbstractComponent) target).getParent();

                    if (complexGrid.isEditorActive() && !(targetParent instanceof VerticalLayout)) {
                        try {
                            complexGrid.saveEditor();
                            complexGrid.cancelEditor();
                            complexGrid.focus();
                        } catch (FieldGroup.CommitException e) {
                            e.printStackTrace();
                        }
                    }
                }

            });


    /* ---------------- GRID COLUMN NAV ------------------------ */

    TextField navEditField = new TextField();

    navEditField.setNullRepresentation("");

    navEditField.addFocusListener(new FieldEvents.FocusListener() {
        @Override
        public void focus(FieldEvents.FocusEvent event) {
            navEditField.selectAll();
        }
    });

    navEditField.addShortcutListener(
            new AbstractField.FocusShortcut(navEditField, ShortcutAction.KeyCode.ENTER, null) {

                @Override
                public void handleAction(Object sender, Object target) {

                    Object targetParent = ((AbstractComponent) target).getParent();

                    if (complexGrid.isEditorActive() && !(targetParent instanceof VerticalLayout)) {
                        try {
                            complexGrid.saveEditor();
                            complexGrid.cancelEditor();
                            complexGrid.focus();
                        } catch (FieldGroup.CommitException e) {
                            e.printStackTrace();
                        }
                    }
                }

            });


    /* ---------------- GRID COLUMN SHARES ------------------------ */

    TextField sharesEditField = new TextField();

    sharesEditField.setNullRepresentation("");

    sharesEditField.addFocusListener(new FieldEvents.FocusListener() {
        @Override
        public void focus(FieldEvents.FocusEvent event) {
            sharesEditField.selectAll();
        }
    });

    sharesEditField.addShortcutListener(
            new AbstractField.FocusShortcut(sharesEditField, ShortcutAction.KeyCode.ENTER, null) {

                @Override
                public void handleAction(Object sender, Object target) {

                    Object targetParent = ((AbstractComponent) target).getParent();

                    if (complexGrid.isEditorActive() && !(targetParent instanceof VerticalLayout)) {
                        try {
                            complexGrid.saveEditor();
                            complexGrid.cancelEditor();
                            complexGrid.focus();
                        } catch (FieldGroup.CommitException e) {
                            e.printStackTrace();
                        }
                    }
                }

            });

    complexGrid.setCellStyleGenerator(cellRef -> {// Java 8

        int tna;
        float nav;

        ComplexModuleData d = (ComplexModuleData) cellRef.getItemId();
        boolean etf = d.getClasstype() == 5;
        String style = "custom-style";

        if ("tna".equals(cellRef.getPropertyId())) {
            try {
                tna = cellRef.getValue() == null ? 0 : Util.removeCommas(cellRef.getValue().toString()).intValue();
                TnaValidatorGrid tnaVal = new TnaValidatorGrid(d.getTnaold() == null ? 0 : d.getTnaold().intValue());

                if (!tnaVal.isValid(tna))
                    style = "custom-style supercell";
                else
                    style = "custom-style";
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if ("nav".equals(cellRef.getPropertyId())) {
            try {
                nav = cellRef.getValue() == null ? 0 : Float.parseFloat(cellRef.getValue().toString());
                NavValidatorGrid navVal = new NavValidatorGrid(d.getNavold() == null ? 0 : d.getNavold().floatValue(), etf);

                if (!navVal.isValid(nav))
                    style = "custom-style supercell";
                else
                    style = "custom-style";
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else
            style = null;

        return style;
    });

    complexGrid.addSelectionListener(new SelectionEvent.SelectionListener() {
        @Override
        public void select(SelectionEvent selectionEvent) {

            complexGrid.getColumn("tna").setEditorField(tnaEditField);
            complexGrid.getColumn("nav").setEditorField(navEditField);
            complexGrid.getColumn("shares").setEditorField(sharesEditField);

            Object obj = complexGrid.getSelectedRow();

            if (obj != null && obj instanceof ComplexModuleData) {
                lastSelectedRow = (ComplexModuleData) obj;
                rowFundClicked(lastSelectedRow);
            } else {
                rowFundClicked(null);
            }
        }
    });

    complexGrid.addShortcutListener(new ShortcutListener("DOWN",
            ShortcutAction.KeyCode.ARROW_DOWN, null) {
        @Override
        public void handleAction(Object sender, Object target) {
            if (target == null) {
                return;
            }
            Object targetParent = ((AbstractComponent) target).getParent();
            if ((targetParent != null) && (targetParent instanceof Grid)) {
                Grid targetGrid = (Grid) targetParent;
                if (targetGrid.isEditorActive()) {
                    try {
                        targetGrid.saveEditor();
                        targetGrid.cancelEditor();
                        targetGrid.focus();
                    } catch (FieldGroup.CommitException e) {
                        Notification.show("Validation failed");
                    }
                }
            }
        }
    });


    complexGrid.addShortcutListener(new ShortcutListener("UP",
            ShortcutAction.KeyCode.ARROW_UP, null) {
        @Override
        public void handleAction(Object sender, Object target) {
            if (target == null) {
                return;
            }
//                logger.info("----> UP KEY <----");
            Object targetParent = ((AbstractComponent) target).getParent();
            if ((targetParent != null) && (targetParent instanceof Grid)) {
                Grid targetGrid = (Grid) targetParent;

                if (targetGrid.isEditorActive()) {
                    try {
                        targetGrid.saveEditor();
                        targetGrid.cancelEditor();
                        targetGrid.focus();
                    } catch (FieldGroup.CommitException e) {
                        Notification.show("Validation failed");
                    }
                }
            }
        }
    });


    complexGrid.addBlurListener(new InnerComplexGridBlurListener());


    /* ------------------- BUTTON SECTION FOR TNA NAV AND SHARES -------------- */

    complexGrid.getColumn("tnac")
            .setRenderer(new ButtonRenderer(e -> { // Java 8
                if (!hasConfirmationPermission())
                    return;
                ComplexModuleData d = (ComplexModuleData) e.getItemId();
                complexGrid.select(manageItemId(e.getItemId()));
                if (complexGrid.isEnabled()) {
                    final ConfirmationWindow results = new ConfirmationWindow(dao, ConfirmationWindow.TNA_TYPE, d.getFundid(), selectedDate, d.getIob(), d.getClasstype());
                    UI.getCurrent().addWindow(results);
                    results.addFocusListener(new FieldEvents.FocusListener() {
                        @Override
                        public void focus(FieldEvents.FocusEvent focusEvent) {
                            results.grabFocus();
                        }
                    });
                }
            }));

    complexGrid.getColumn("navc")
            .setRenderer(new ButtonRenderer(e -> {// Java 8
                if (!hasConfirmationPermission())
                    return;
                ComplexModuleData d = (ComplexModuleData) e.getItemId();
                complexGrid.select(manageItemId(e.getItemId()));
                if (complexGrid.isEnabled()) {
                    final ConfirmationWindow results = new ConfirmationWindow(dao, ConfirmationWindow.NAV_TYPE, d.getFundid(), selectedDate, d.getIob(), d.getClasstype());
                    UI.getCurrent().addWindow(results);
                    results.addFocusListener(new FieldEvents.FocusListener() {
                        @Override
                        public void focus(FieldEvents.FocusEvent focusEvent) {
                            results.grabFocus();
                        }
                    });
                }
            }));


    complexGrid.getColumn("sharesc")
            .setRenderer(new ButtonRenderer(e -> {// Java 8
                if (!hasConfirmationPermission())
                    return;
                ComplexModuleData d = (ComplexModuleData) e.getItemId();
                complexGrid.select(manageItemId(e.getItemId()));
                if (complexGrid.isEnabled()) {
                    final ConfirmationWindow results = new ConfirmationWindow(dao, ConfirmationWindow.SHARES_TYPE, d.getFundid(), selectedDate, d.getIob(), d.getClasstype());
                    UI.getCurrent().addWindow(results);
                    results.addFocusListener(new FieldEvents.FocusListener() {
                        @Override
                        public void focus(FieldEvents.FocusEvent focusEvent) {
                            results.grabFocus();
                        }
                    });
                }
            }));

    GridExtension.apply(complexGrid);

...
...
}

I and I assume the majority of vaadin developers use Eclipse. Server-wise Jetty and Tomcats are once i work with and they should work fine.
I also remember people having problems when using IntelliJ, especially when using the Community Edition ( there is even a Blog post about it now) but a lot of problems can be resolved using Maven.

If you can you should try out Eclipse with the Vaadin Plugin. I also recommend for testing purposes to then use Ivy as a dependency management because it is better integrated into the Vaadin Plugin than maven.

Generally i assume your IntelliJ is having a problem with the GWT client side as your widgetset compilation didn’t work properly when we were talking about the TextFieldRenderer if i remember correctly. This might linked to your current problem but could also not be.

Did you test my simplistic code example in your IntelliJ once to see if the environment really might have a problem even with basic Vaadin Grid code?

I will try this application in Eclipse, maybe this will help (probably not today, though). We purchased IntelliJ Ultimate, but they have a weird upgrade policy where you have to pay for every upgrade (or so it seems), so we are back a few versions on 13.1. This may have something to do with it as well.

I tried your code in the sandbox and it worked fine. I am now trying to figure out why things break when I when I set the EditorField earlier. I will post again when I have some good info.

I have now tried this in different ways and seem to have a better understanding of what is causing these Warnings, but not sure how to fix it.

In regards to how to bind EditorField, it looks like I can bind it fine when I have data in the Grid, but it doesn’t like it when I have an empty grid. Also, since my Grid is being refreshed a lot with different data sets, I also added a boolean to track whether or not the EditorField has already been set. Right now, I am only setting the EditorField on first data load.

As for the warnings, they only appear when I begin to navigate through the grid quickly. If I hold the arrow button down or click around quickly, I get those warning messages.

Again, this isn’t critical, but at the very least I would like to suppress these messages so my log file isn’t filling up so quickly. A ton of work will be done in this grid, so I wouldn’t want to fill the logs with warning messages that nobody needs.

Any thoughts? Or should I spend my time on things a bit more productive?