How to veto a table selection?

Hello,

this one should be simple: assume there is a master table and a form to edit the selected table row.

  1. User selects a row
  2. User edits the row data using the form which causes the form model to be modified
  3. User selects a different row (without previously saving the modifications)
  4. System displays a popup “Would you like to save your changes?” with 3 possible answers:
    Yes
    ,
    No
    ,
    Cancel
    .


Yes
and
No
are simple: just save/do not save and let the selection move on.


Cancel
has a simple but problematic solution: do not save and move the selection back.
The problem with this simple solution is that the selection of the different row may cause computations which (for example) modify the newly selected item. When the selection is moved back programmatically, this would result in unwanted side effects (like another “Would you like to save your changes?” question which does not make sense to the user).

Is there Vaadin 6.8/Vaadin 7 compatible solution to implement
Cancel
which allows vetoing a selection change via ValueChangeListener or ItemChangeListener or something else?

Thanks,
Sascha

What I do in similar cases is to show the form in realOnly mode, ( with an Edit Button ).
User click Edit , and I disable the Table until the user click Save or Cancel

You could remove your listener before you programmatically change the selection back , then add it again after the programatic change ( this might even be rquired if your form is buffered , or you might lose all the changes your user made ).

I dont think there is a simple way to veto a selection the way you would want to do.

This is a solution, but very inconvenient for the user. This is not acceptable over here ;-).

This actually works, but it is a really dirty, hard-to-understand hack especially when implemented in a generic way. What if there are multiple ValueChangeListeners? Or ItemClickListeners? Is it guaranteed that ItemClickListeners execute prior to ValueChangeListeners?

To me this sounds like a standard requirement which should be really really simple to implement. For example, Vaadin could provide a VetoableValueChangeListener which is guaranteed to execute prior to the standard (non-vetoable) ValueChangeListeners. If any of the VetoableValueChangeListeners throws a veto exception, the whole value change is stopped. The whole handling of the selection could (should) be done by Vaadin.

Hello,
to implement similar solution I overrided Table class to not allow changing the selection if a condition is not satisfied:

package cz.pse.services.component.table;

/**
 * {@link com.vaadin.ui.Table}, that does not allow to click to another row if current row is invalid.
 *
 */
@SuppressWarnings("serial")
public class Table extends com.vaadin.ui.Table {

    private ValueValidator validator;
    
    public Table(String caption){
        super(caption);
    }
    
    public Table() {
        super();
    }

    public void changeVariables(Object source, java.util.Map<String,Object> variables) {
        if (!variables.containsKey("selected") || validator == null || validator.isValid(getValue())) {
            super.changeVariables(source, variables);
            return;
        }
        markAsDirty();
    }

    public void setValidator(ValueValidator validator) {
        this.validator = validator;
    };
    
    /**
     * Checks if given value is valid.
     *
     */
    public interface ValueValidator {
        
        boolean isValid(Object value);
        
    }
}

My validator checks if the edited value is valid and, if not, shows the popup window with message and OK button.

Thanks => Agata Vackova

I had no time to try it yet, but it seems like a reasonable solution. I hope the planned redesign of the Table in (see https://vaadin.com/blog/-/blogs/vaadin-development-team-update-06-07-2013) allows a similar approach.

now I had the time to try the proposed solution. Until now it is the best I have found but it does not seem to be really “clean” to me.

If a user tries to leave an invalid row by clicking with the mouse,

  • the selection will jump to the new row and stay there until the ValueValidator has been executed. So if the ValueValidator opens the “Would you like to save your changes?” dialog, the selection stays on the new row until the user answers the question. This is objectionable.
  • the dotted border will stay there even after the ValueValidator has been executed which leads to some confusion.

If a user tries to leave an invalid row by pressing cursor down, the behaviour is the same. However, if he presses cursor down multiple times or if he just uses PageDown, the selected row will even leave the visible area. This is hard to explain to the user.
Is there a way to avoid this “dotted border” behaviour or can we restore the row decorated with the dotted border programmatically?

I do not want to hide the dotted row (i.e. via CSS) since it is important at least for multi-select tables. But it should always indicate the last
sucessfully
selected row.

Thanks

Table does normally optimistically change the visual selection immediately, before informing the server about the value change. This is because always waiting for the server would impose an unacceptable delay between the user interaction and the visual change.

In the use case described in this thread, the veto should be enabled only when there are actually unsaved changes present, so however this feature might be implemented, it should be easily toggleable.