Navigating cursor between table cells is lost

I want to navigate across editable cells in a table using “tab” key but when I hit on the table the cursor doesn’t move to the next tab, rather lost the focus. for example in the image below, after I have edited the value 8, i want my cursor moved to the next column (Allowance) when I hit on the “tab” button. How can I get this working?

image

Hello,

It is a known bug that does not have an easy fix. For now, you use a workaround from these topics:

The main idea is to replace remained columns, which are not editable, by generated columns with Label or Table.PlainTextCell.

Thank you @Pinyazhin
I have taken a look at the sample project that you shared in one of the links you provided. In my case, I have two other types of fields

  1. Enum
  2. Another Entity

In this case, what will be the solution in generating table columns? I have attached the modified project with those fields and would appreciate it if you please help.ftablefocus.zip (91.0 KB)

If you have Entity or Enum types I think it is better to use MetadataTools#format(). For instance:

@Inject
private Table<Project> projectsTable;
@Inject
private MetadataTools metadataTools;

@Subscribe
public void onInit(InitEvent event) {
    projectsTable.getColumns().forEach(column -> {
        if (!column.isEditable()) {
            column.setColumnGenerator(project -> {
                MetaPropertyPath mpp = column.getMetaPropertyPathNN();
                Object value = project.getValueEx(mpp);
                return new Table.PlainTextCell(metadataTools.format(value));
            });
        }
    });
}
1 Like

Thank you so much.

Hi @Pinyazhin
Could you please suggest when the inactive column is a boolean data type?

image

I tried the following but not working as expected.

column.setColumnGenerator(entity->{
                Label<String> label = uiComponents.create(Label.class);
                Object val = entity.getValueEx(column.getIdString());
                label.setValue(metadataTools.format(val));
                return label;
            });

Hello,

Both solutions (your and code in my answer above) works for me. Could you check that you set the generator to the correct column?
Try to reproduce in another demo project, if this behavior still presents, please share the code of controller and XML descriptor or share the demo project.

Hi @Pinyazhin
Thanks. I tried in a demo project that works but strange that it doesn’t work in the same way in my main project. The only difference I see is, the logical column shows differently when it is uneditable as below:

in my project: it still shows as checkbox
image

But in the test project, it shows in text as True / False as below
image

Could this be the reason? But when the checkbox is behaving differently? I am using the same platform version in both projects. I used the same code in both cases but behaving differently.

When we use setColumnGenerator() we replace the content of the cell with some Component. In our case, we create Label (or PlainTextCell) with a text value. MetadataTools#format() for boolean returns text value, e.g. “True” or “False” for English locale.
If you still see the checkBox, it means that the generator is not set to the column. It would be helpful if you send an XML descriptor and screen controller files to investigate the issue.

Hi @Pinyazhin
Thanks for being so kind helping me patiently. I tried both approaches i.e. Label and PlainTextCell but getting the same outcome.

Here is the xml file and controller.

import com.haulmont.cuba.core.global.MetadataTools;
import com.haulmont.cuba.core.global.PersistenceHelper;
import com.haulmont.cuba.gui.UiComponents;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.model.CollectionPropertyContainer;
import com.haulmont.cuba.gui.model.DataContext;
import com.haulmont.cuba.gui.model.InstanceContainer;
import com.haulmont.cuba.gui.screen.*;
import com.myapp.erp.entity.gen.Holiday;
import com.myapp.erp.entity.gen.HolidayFloatDate;
import com.myapp.erp.entity.gen.HolidayType;

import javax.inject.Inject;

@UiController("erp$Holiday.edit")
@UiDescriptor("holiday-edit.xml")
@EditedEntityContainer("holidayDc")
@LoadDataBeforeShow
public class HolidayEdit extends StandardEditor<Holiday> {
    @Inject
    private GroupBoxLayout holidayFloatDateBox;
    @Inject
    private TextField<Integer> dayField;
    @Inject
    private TextField<Integer> monthField;
    @Inject
    private DataContext dataContext;
    @Inject
    private CollectionPropertyContainer<HolidayFloatDate> holidayFloatDateDc;
    @Inject
    private Table<HolidayFloatDate> holidayFloatDateTable;
    @Inject
    private MetadataTools metadataTools;
    @Inject
    private UiComponents uiComponents;

    @Subscribe
    public void onInitEntity(InitEntityEvent<Holiday> event) {
    
  holidayFloatDateTable.getColumns().forEach(column -> {
            if (!column.isEditable()) {
                column.setColumnGenerator(entity->{
                    MetaPropertyPath mpp = column.getMetaPropertyPathNN();
                    Object value = entity.getValueEx(mpp);
                    return new Table.PlainTextCell(metadataTools.format(value));
                });
            }
        });

    }


    @Subscribe
    public void onAfterShow(AfterShowEvent event) {
        if(!PersistenceHelper.isNew(getEditedEntity()) && getEditedEntity().getHolidayType()!=null){
            holidayFloatDateBox.setVisible(getEditedEntity().getHolidayType().equals(HolidayType.FLOATING_DATE));
            dayField.setVisible(!getEditedEntity().getHolidayType().equals(HolidayType.FLOATING_DATE));
            monthField.setVisible(!getEditedEntity().getHolidayType().equals(HolidayType.FLOATING_DATE));
        }
    }



    @Subscribe(id = "holidayDc", target = Target.DATA_CONTAINER)
    public void onHolidayDcItemPropertyChange(InstanceContainer.ItemPropertyChangeEvent<Holiday> event) {
        if("holidayType".equals(event.getProperty())){
            if(event.getValue()!=null){
                holidayFloatDateBox.setVisible(event.getValue().equals(HolidayType.FLOATING_DATE));
                dayField.setVisible(!event.getValue().equals(HolidayType.FLOATING_DATE));
                monthField.setVisible(!event.getValue().equals(HolidayType.FLOATING_DATE));
            }
        }
    }

    @Subscribe("holidayFloatDateTable.create")
    public void onHolidayFloatDateTableCreate(Action.ActionPerformedEvent event) {
        HolidayFloatDate floatDate = dataContext.create(HolidayFloatDate.class);
        floatDate.setUsed(false);
        floatDate.setHoliday(getEditedEntity());
        holidayFloatDateDc.getMutableItems().add(floatDate);
    }
}

Here is the content of the xml file

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
  ~ Copyright (c) 2020 INTEACC Softech Solutions
  -->

<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
        caption="msg://holidayEdit.caption"
        focusComponent="form"
        messagesPack="com.myapp.erp.web.gen.holiday">
    <data>
        <instance id="holidayDc"
                  class="com.myapp.erp.entity.gen.Holiday">
            <view extends="_local">
                <property name="holidayFloatDate" view="_minimal">
                    <property name="year"/>
                    <property name="month"/>
                    <property name="day"/>
                    <property name="used"/>
                </property>
            </view>
            <loader/>
            <collection id="holidayFloatDateDc" property="holidayFloatDate"/>
        </instance>
    </data>
    <dialogMode height="600"
                width="800"/>
    <layout expand="holidayFloatDateBox" spacing="true">
        <form id="form" dataContainer="holidayDc" captionPosition="TOP">
            <column>
                <textField id="nameField" property="name" colspan="3" width="100%"/>
                <lookupField id="holidayTypeField" property="holidayType"/>
            </column>
            <column width="50">
                <textField id="dayField" property="day"/>
            </column>
            <column width="50">
                <textField id="monthField" property="month"/>
                <textField id="tenantIdField" property="tenantId"/>
            </column>

        </form>
        <groupBox id="holidayFloatDateBox" caption="msg://com.myapp.erp.entity.gen/Holiday.holidayFloatDate">
            <table id="holidayFloatDateTable" dataContainer="holidayFloatDateDc" width="100%" height="100%"
                   editable="true">
                <actions>
                    <action id="create" type="create"/>
                    <action id="remove" type="remove"/>
                </actions>
                <columns>
                    <column id="year" editable="true"/>
                    <column id="month" editable="true"/>
                    <column id="day" editable="true"/>
                    <column id="used" editable="false"/>
                </columns>
                <buttonsPanel>
                    <button action="holidayFloatDateTable.create"/>
                    <button action="holidayFloatDateTable.remove"/>
                </buttonsPanel>
            </table>
        </groupBox>
        <hbox id="editActions" spacing="true">
            <button id="commitAndCloseBtn" action="windowCommitAndClose"/>
            <button id="closeBtn" action="windowClose"/>
        </hbox>
    </layout>
</window>

InitEntityEvent is sent only when a new entity instance is set to an edited entity container. Your issue occurs only for editing entity instance.

Try to move the code for table columns to the InitEvent:

@Subscribe
public void onInit(InitEvent event) {
    holidayFloatDateTable.getColumns().forEach(column -> {
        if (!column.isEditable()) {
            column.setColumnGenerator(entity-> {
                MetaPropertyPath mpp = column.getMetaPropertyPathNN();
                Object value = entity.getValueEx(mpp);
                return new Table.PlainTextCell(metadataTools.format(value));
            });
        }
    });
}
1 Like

Thank you. It worked.