Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Listgrid: how to locally load multiple invalid rows and let the user correct them

    I have to produce an editable listGrid for a well known set or records that could initially have invalid data.
    The user should be able to notice invalid contents and edit cells accordingly in order to correct and save data.
    The problem is that the listgrid doesn't show error messages nor error icons until the user tries to edit a cell (even if its contents are already invalid). Only after changing cell contents to a new invalid value the error marker remains visible.
    I've tried almost every combination I can think of, loading invalid data on a clientonly datasource, and even adding directly to the listgrid, disabling autosave and also setting saveLocally: no results.
    Is there any way to load invalid data on an editable listgrid somewhat marking all invalid cells (possibly with error message tooltips)?

    Here you are an example snippet:
    Code:
    final DataSource dataSource = new DataSource ();
    dataSource.setClientOnly (true);
    
    final ListGrid grid = new ListGrid ();
    grid.setAutoFetchData (true);
    grid.setCanEdit (true);
    grid.setAutoSaveEdits (false);
    grid.setValidateByCell (true);
    grid.setEditEvent (ListGridEditEvent.CLICK);
    
    
    final List<Record> testData = new ArrayList<Record> ();
    {//data initialization
        {
            final Record record = new Record ();
            record.setAttribute ("id", "1");
            record.setAttribute ("budgetA", "asdf");
            record.setAttribute ("budgetB", 123d);
            record.setAttribute ("foo", "fooXYZ");
            testData.add (record);
        }
        {
            final Record record = new Record ();
            record.setAttribute ("id", "2");
            record.setAttribute ("budgetA", 789);
            record.setAttribute ("foo", "qwerty");
            testData.add (record);
        }
    }
    
    grid.addDrawHandler (new DrawHandler() {
        
        @Override
        public void onDraw (DrawEvent event) {
            if (grid.isDrawn ()) {
                GWT.log ("adding live data");
                for (Record record : testData) {
                    grid.addData (record);
                }
            } else {
                GWT.log ("data add SKIPPED!!!");
            }
        }
    });
    
    {//datasource fields initialization
        final DataSourceTextField keyField = new DataSourceTextField ("id", "ID");
        keyField.setPrimaryKey (true);
        final DataSourceFloatField budgetAField = new DataSourceFloatField ("budgetA", "Budget A");
        
        final DataSourceFloatField budgetBField = new DataSourceFloatField ("budgetB", "Budget B");
        {
            final Validator myValidator = new CustomValidator() {
                
                @Override
                protected boolean condition (Object value) {
                    GWT.log ("budgetB validation value: "+value);
                    if (value==null) {
                        GWT.log ("budgetB is not valid: "+value);
                        setErrorMessage ("The value is mandatory");
                        return false;
                    }
                    return true;
                }
            };
            budgetBField.setValidators (myValidator);
            
        }
        
        final DataSourceTextField fooField = new DataSourceTextField ("foo", "Foo");
        {
            final Validator myValidator = new CustomValidator() {
                
                @Override
                protected boolean condition (Object value) {
                    if (value==null) {
                        setErrorMessage ("The value is mandatory");
                        return false;
                    }
                    if (!(value instanceof String)) {
                        setErrorMessage ("Only textual values admitted");
                        return false;
                    }
                    if (!((String)value).startsWith ("foo")) {
                        setErrorMessage ("Should start with 'foo'");
                        return false;
                    }
                    return true;
                }
            };
            fooField.setValidators (myValidator);
        }
        
        dataSource.setFields (keyField, budgetAField, budgetBField, fooField);
    }
    
    {
        final ListGridField budgetAField = new ListGridField ("budgetA", "Budget A (float)");
        final ListGridField budgetBField = new ListGridField ("budgetB", "Budget B (mandatory, float)");
        final ListGridField fooField = new ListGridField ("foo", "Foo (mandatory, and should start with 'foo')");
    
        grid.setFields (budgetAField, budgetBField, fooField);
    }
    
    grid.setDataSource (dataSource);
    
    
    ...
    I'd also need to set ListGrid.setAlwaysShowEditors (true) but it seems to make things worse (that way invalid contents markers are shown only on focused rows).
    [ATTACH]4677[/ATTACH] is a complete test case entry point.

    Tried with SmartGWT 3.0 [SmartClient Version: v8.2p_2012-10-16/LGPL Development Only (built 2012-10-16)]
    Last edited by d.cavestro; 30 Oct 2012, 00:40. Reason: Added link to the test case

    #2
    Take a look at the Grid Editing overview: data loaded from the server is assumed always valid. To introduce values that are treated like (potentially invalid) user edits, use setEditValues().

    Comment


      #3
      Originally posted by Isomorphic View Post
      To introduce values that are treated like (potentially invalid) user edits, use setEditValues().
      Thank you,
      but setEditValues() seems to solve only partially my problem.
      Using something like
      Code:
      for (int i=0;i<testData.size ();i++) {
          grid.setEditValues (i, testData.get (i).toMap ());
      }
      I obtain the same effect as using
      Code:
      for (Record record : testData) {
          grid.startEditingNew (record);
      }
      that is pressing ESC to discard some cell changes I have the bad side effect of loosing the entire row, while my UI should let the user correct data on a well known set of (potentially invalid) rows.
      Moreover while using startEditingNew I immediately get the error markers, using setEditValues I have to put focus and then abandon a row in order to see error markers on it.

      The only viable workaround I've found till now in order to always have invalid data markers and still keep rows is to entirely disable discarding edits overriding the javascript function through JSNI this way
      Code:
      class MyListGrid extends ListGrid {
          @Override
          protected native JavaScriptObject create()
          /*-{
              var config = this.@com.smartgwt.client.widgets.BaseWidget::getConfig()();
              var scClassName = this.@com.smartgwt.client.widgets.BaseWidget::scClassName;
              
              var widget = $wnd.isc[scClassName].create(config);
              
              //disables discarding edits in order to preserve unsaved rows when the user press ESC  
              widget.discardEdits = function (rowNum, colNum, dontHideEditor) {
      //          return this.Super("discardEdits", [rowNum, colNum, true]);
                  return false;
              }
      
              this.@com.smartgwt.client.widgets.BaseWidget::doInit()();
              return widget;
          }-*/;
      }
      That seems enough... just hope it doesn't lead to ugly side effects some day.
      Any better solution?

      PS: is there any way to show validation error markers even when editing is not enabled? Cause even setting custom cell formatters I have no access to validation error messages.
      Last edited by d.cavestro; 31 Oct 2012, 01:09. Reason: Added PS

      Comment


        #4
        You could just use BodyKeyPress and cancel() the event, much simpler.

        Keep in mind you can also supply a dataset and then use setEditValues() to add changes on top of that. So depending on what you are doing, the dataset you supply might be just a bunch of records with primaryKey values only, then all other data is expressed as editValues.

        Validation errors do not exist for data that has not been edited. But when errors exist they are shown whether the row is the active editor row or not.

        Comment


          #5
          At the end, using ListGrid.setData () and then ListGrid.startEditing() for every cell did the trick, without disabling cell editing dismission.

          Code:
          grid.setData(testData);
          
          //forces editing as a rubber stamp in order to mark invalid values
          final int totalRows = grid.getTotalRows();
          for (int rowNum = 0; rowNum < totalRows; rowNum++)
          {
              final ListGridField[] cols = grid.getFields();
              for (int colNum = 0; colNum < cols.length; colNum++)
              {
                  grid.startEditing(rowNum, colNum, true);
              }
          }
          grid.setCanEdit(canEdit);
          The only remaining problem is that a "readonly" table still doesn't show error markers unless I disable editing only after it has been drawn (with an unreliable timer hack).
          Is there any reliable way to disable table editing only after it has been rendered?
          Please note I had to embed my table into a GWT component, hence there could be some misbehavior due to mixing the two libraries.

          Comment

          Working...
          X