Search code examples
javauser-interfacecheckboxgwtcelltable

GWT - How to programmatically uncheck a CheckboxCell when another CheckboxCell is checked?


Given two CheckboxCell's checkboxA and checkboxB, how can I programmatically uncheck checkboxB if checkboxA is unchecked? From what I've tried, I'm able to set the value of checkboxB = false when checkboxA = false, but this change is not being reflected in the UI.

My table with the checkboxes -

public void buildTable() {
    myDataProvider.addDataDisplay(myTable);

    // other columns

    Column<Note, Boolean> checkboxA = new Column<Note, Boolean>(new CheckboxCell()){

        @Override
        public Boolean getValue(Note object) {
            return object.isAChecked();
        }

    };

    checkboxA.setFieldUpdater(new FieldUpdater<Note, Boolean>() {

        @Override
        public void update(int index, Note object, Boolean value) {
            performCheckboxAOperation(object, value);
        }
    });

    Column<Note, Boolean> checkboxB = new Column<Note, Boolean>(new CheckboxCell()){

        @Override
        public Boolean getValue(Note object) {
            return object.isBChecked();
        }

    };

    checkboxB.setFieldUpdater(new FieldUpdater<Note, Boolean>() {

        @Override
        public void update(int index, Note object, Boolean value) {
            performCheckboxBOperation(object, value);
        }
    });

    myTable.addColumn(checkboxA, "BOX A");
    myTable.addColumn(checkboxB, "BOX B");
}

Method to store checkbox A's value in the DB, and if checkboxA == false, also set checkboxB = false in the DB -

public void performCheckboxAOperation(Note note, Boolean bool) {
    this.presenter.performBoxOperation(note, bool, new AsyncCallback<CNote>() {

        @Override
        public void onFailure(Throwable caught) {
            // error logic
        }

        @Override
        public void onSuccess(CompanyNote result) {
            cleanupDataProvider.flush();

            if (result.isAChecked() == false) {
                if (result.isBChecked() == true) {
                    unsetB(result);
                }
            }
        }
    });
}

This is my method to unset checkboxB which is changing the value in the DB but not in the UI -

private void unsetB(Note note) {
    this.presenter.performBoxOperation(note, false, new AsyncCallback<Note>() {

        @Override
        public void onFailure(Throwable caught) {
            // error logic
        }

        @Override
        public void onSuccess(Note result) {
            myDataProvider.flush();
            myTable.redraw();
        }
    });
}

From what I understand, ListDataProvider needs to be flushed for the changes to be reflected in the UI. This has worked very well for all the other fields in the table, but it is not working with CheckboxCells.

I've already tried to redraw() the table as can be seen above but without any luck.

So what should I be doing to trigger a UI change in another CheckboxCell when one CheckboxCell is clicked?


Solution

  • I think that you forgot to actually change the object's value.

    private void unsetB(final Note note) {
        this.presenter.performBoxOperation(note, false, new AsyncCallback<Note>() {
            // ...
            @Override
            public void onSuccess(Note result) {
                note.setB(false);  // set B value or copy `result` to `note`
                                   // (`note` must be final)
                myDataProvider.flush();
                myTable.redraw();
            }
        });
    }
    

    Also, in performCheckboxAOperation you call unsetB(result); - it should be unsetB(note);

    You need to understand that in onSuccess you get a copy of Note. The result object is not in the DataProvider, note is. And you should change note's value.