Announcement

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

    Validate all records in a ListGrid

    Hi,
    I couldn't find a good example in the showcase, so I made my own.

    I want to actively do a validation on all records in the ListGrid, but it seems that validators are only triggered when the user changed the field. For instance, in this example, 3 fields are put required, yet the validator (lgUsers.validateRow(rowNum) -> "This method may also be called directly to perform row level validation at any time" ) do not trigger the "field is required" if the field is still empty.

    This is something that works perfectly on forms, but it seems to be hard to do on all ListGrid.


    In this example, you can add a record to the grid, fill in Email only and press validate without a validation error on the other fields (not expected).

    Code:
    public class AdHocListGridValidation implements EntryPoint {
    	
    	private final ListGrid lgUsers = new ListGrid();
    	private Button btnAdd = new Button("Add Row");
    	private Button btnValidate = new Button("Add Validate");
    	
    	public void onModuleLoad() {		
    		VLayout main = getMainCanvas();	
    		main.draw();
    	}
    	
    	
    	public VLayout getMainCanvas() {
    			
    		
    		RegExpValidator regExpValidator = new RegExpValidator();  
            regExpValidator.setExpression("^([a-zA-Z0-9_.\\-+])+@(([a-zA-Z0-9\\-])+\\.)+[a-zA-Z0-9]{2,4}$");  
            
    		ListGridField[] fields = new ListGridField[4];
    		fields[0] = new ListGridField("Identification", "Identification");
    		fields[0].setRequired(true);
    		fields[0].setCanEdit(true);
    		
    		fields[1] = new ListGridField("Signonid", "Signonid");
    		fields[1].setCanEdit(true);
    		fields[1].setRequired(true);
    		
    		fields[2] = new ListGridField("Password", "Password");
    		fields[2].setCanEdit(true);
    		fields[2].setRequired(true);
    		
    		PasswordItem item = new PasswordItem();
    		fields[2].setEditorType(item);
    		fields[2].setCellFormatter(new CellFormatter() {
    			public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
    				return "******";
    			}
    		});
    		fields[3] = new ListGridField("Email", "Email");
    		fields[3].setCanEdit(true);		
    		fields[3].setValidators(regExpValidator);
    		
    		lgUsers.setFields(fields);
    		lgUsers.setValidateOnChange(true);		
    		lgUsers.setShowRowNumbers(true);
    		
    		btnAdd.addClickHandler(new AddClickHandler());
    		btnValidate.addClickHandler(new ValidateClickHandler());
    		
    		VLayout main = new VLayout();
    		HLayout btns = new HLayout();
    		main.setWidth100();
    		main.setHeight100();
    		btns.addMember(btnAdd);
    		btns.addMember(btnValidate);
    		main.addMember(lgUsers);
    		main.addMember(btns);
    		
    		return main;
    	}
    	
    	class AddClickHandler implements com.smartgwt.client.widgets.events.ClickHandler{
    		public void onClick(ClickEvent event) {
    			ListGridRecord record = new ListGridRecord();
    			lgUsers.addData(record);			
    		}
    	}
    	
    	
    	class ValidateClickHandler implements com.smartgwt.client.widgets.events.ClickHandler{
    		public void onClick(ClickEvent event) {
    			int rowNum = lgUsers.getRowNumberStart();
    			System.out.println("RowNrStart : " + rowNum);
    			for(ListGridRecord rec : lgUsers.getRecords()){				
    				if(lgUsers.validateRow(rowNum)){
    					System.out.println("validaterow " + rowNum + " TRUE");
    				}else{
    					System.out.println("validaterow " + rowNum + " FALSE");
    				}
    				rowNum++;
    			}		
    		}
    	}
    }
    regards

    SmartGWT LGPL 2.3

    #2
    Data that comes from the server or that you populate via setData() is assumed to be already valid. To have data in the grid treated as though it was user-entered, you can use setEditValues().

    Comment


      #3
      Hello,

      I guess I can understand that. I have added the setEditValue as was suggested, also on each existing record. Validate still is not performed on all, however this only results in a correct validation of my last row in the loop the first time after this seteditvalue is called.

      Other problem: when I click add to add a row, 2 rows are added to the grid.

      Code:
      /**
       * Test case to illustrate trying to perform ad hoc validation on a listgrid.
       * In forms this task is easy to accomplish, in the listgrid this seems not available at all:
       * 
       * The ValidationClickHandler class tries an adhoc validation per row, using the ListGrid.validateRow funtion.
       * Documentation of this methods status: <i>This method may also be called directly to perform row level validation at any time.</i>
       * But it does not seem to work.
       * 
       * I want to be able to perform ad hoc validation of the entire listgrid because adding a new record does not "constitutes" as a "change" for the listgrid.
       * It should be able to validate new records, to avoid users from inserting empty lines in the grid.
       * 
       * /
      public class AdHocListGridValidation implements EntryPoint {
      	
      	private final ListGrid lgUsers = new ListGrid();
      	private Button btnAdd = new Button("Add Row");
      	private Button btnValidate = new Button("Validate");
      	
      	public void onModuleLoad() {		
      		VLayout main = getMainCanvas();	
      		main.draw();
      	}
      	
      	
      	public VLayout getMainCanvas() {
      			
      		
      		RegExpValidator regExpValidator = new RegExpValidator();  
              regExpValidator.setExpression("^([a-zA-Z0-9_.\\-+])+@(([a-zA-Z0-9\\-])+\\.)+[a-zA-Z0-9]{2,4}$");  
              
      		ListGridField[] fields = new ListGridField[4];
      		fields[0] = new ListGridField("Identification", "Identification");
      		fields[0].setRequired(true);
      		fields[0].setCanEdit(true);
      		
      		fields[1] = new ListGridField("Signonid", "Signonid");
      		fields[1].setCanEdit(true);
      		fields[1].setRequired(true);
      		
      		fields[2] = new ListGridField("Password", "Password");
      		fields[2].setCanEdit(true);
      		fields[2].setRequired(true);
      		
      		PasswordItem item = new PasswordItem();
      		fields[2].setEditorType(item);
      		fields[2].setCellFormatter(new CellFormatter() {
      			public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
      				return "******";
      			}
      		});
      		fields[3] = new ListGridField("Email", "Email");
      		fields[3].setCanEdit(true);		
      		fields[3].setValidators(regExpValidator);
      		
      		lgUsers.setFields(fields);
      		lgUsers.setValidateOnChange(true);		
      		lgUsers.setShowRowNumbers(true);
      		
      		btnAdd.addClickHandler(new AddClickHandler());
      		btnValidate.addClickHandler(new ValidateClickHandler());
      		
      		VLayout main = new VLayout();
      		HLayout btns = new HLayout();
      		main.setWidth100();
      		main.setHeight100();
      		btns.addMember(btnAdd);
      		btns.addMember(btnValidate);
      		main.addMember(lgUsers);
      		main.addMember(btns);
      		
      		return main;
      	}
      	
      	class AddClickHandler implements com.smartgwt.client.widgets.events.ClickHandler{
      		public void onClick(ClickEvent event) {
      			ListGridRecord record = new ListGridRecord();
      			lgUsers.addData(record);	
      			int rowNum = lgUsers.getRowNumberStart() + lgUsers.getRecords().length -1;			
      		}
      	}
      	
      
      	class ValidateClickHandler implements com.smartgwt.client.widgets.events.ClickHandler{
      		public void onClick(ClickEvent event) {
      			int rowNum = lgUsers.getRowNumberStart();
      			System.out.println("RowNrStart : " + rowNum);
      			for(ListGridRecord rec : lgUsers.getRecords()){
      				
      				lgUsers.setEditValue(rowNum, "Identification", rec.getAttributeAsString("Identification"));
      				lgUsers.setEditValue(rowNum, "Signonid", rec.getAttributeAsString("Signonid"));
      				lgUsers.setEditValue(rowNum, "Password", rec.getAttributeAsString("Password"));
      				lgUsers.setEditValue(rowNum, "Email", rec.getAttributeAsString("Email"));
      				if(lgUsers.validateRow(rowNum)){
      					System.out.println("row " + rowNum + ": TRUE");
      				}else{
      					System.out.println("row " + rowNum + ": FALSE");
      				}
      				rowNum++;
      			}		
      		}
      	}
      }

      Comment


        #4
        It looks like what you're doing is setting editValues to exact the current value of the record, which (correctly) is the same thing as not setting an editValue.

        To explicitly provide data as though the user had entered it, leave the records blank and provide all the data as editValues only.

        Comment


          #5
          Hi,

          To recap: I'm trying to bring the exclamation mark on every NULL field which is marked as required by using the validate function.
          If I actually set a value on the field by using editValues, that means I can't check for the isRequired, right?



          Also, there's still this problem with the add: it adds 2 rows instead of just 1.

          Comment


            #6
            If the new value is null, don't call setEditValue() for that field, and if there's no value in the record, it will be flagged as a validation error if the field is required.

            Don't call addData() to get the data into the grid - that's going to try to save data back to the DataSource. The initial data (blank rows except for primary key values presumably) can be provided as a RecordList or ResultSet, each easy to retrieve using DataSource.fetchData(), and then editValues can be overlaid on this.

            Comment


              #7
              Hi,

              It doesn't concern validation of existing data that is used to populate the grid.

              It concerns valdiation of mandatory fields in a listgrid. If these fields are not edited, no automatic validation is triggered
              ==> it should be possible to trigger the validation manually + validation should fail if no value is in the mandatory field.


              CASE:
              1. User adds row via AddRow which creates an empty row in listgrid (some fields in that row are set mandatory)
              2. User presses the save , no validation ever occurred and data is saved
              ==> NOK


              During save we want to trigger the validation of these rows, however it seems imposssible to do this. I have implemented the last suggestion, but doesn't work either. Mind I do NOT use a datasource.
              (In the example I try validating all rows, actually only the added rows must be validated)
              With the modified sample,
              I get following issues:
              Issue 1. First time I press addRow : 2 rows are added.
              (screenshot 1)


              Issue 2. I add 3 more rows and then press validate: only the last row in the loop is actually validated.
              (screenshot 2)


              The log of the validate loop (only knows of 4 rows , probably issue with the two rows that were added during first add, are not "really added" both, but only 1) (See previous post for the code):
              RowNrStart : 1
              row 1: TRUE
              row 2: TRUE
              row 3: TRUE
              row 4: FALSE

              => NOK , the exclamation mark should be there in all rows.
              How can I achieve this?


              thanks for the ideas
              Attached Files

              Comment


                #8
                You're adding a row via addData() - this means the new row is saved, and then provided to the grid via cache sync as an already-valid row that exists as part of saved data.

                Instead, use startEditingNew() to add a new row that is considered user-provided data.

                See the ListGrid Editing Overview for further context.

                Comment


                  #9
                  Cool thanks for the advice.
                  Got it working :)
                  Attached Files

                  Comment


                    #10
                    The same problem still remains in TreeGrid where startEditingNew is not a good way to add rows because they are added at end of the list.

                    Documentation says that the better way is to add TreeNode by using grid.data.add() but when I do this I end up with the same problem as original poster had. The newly added row is not validated.

                    I tried adding empty {} data to particular parent node and then calling setEditValues(). This way I got one row validated but after adding more rows only the last one display exclamation marks on required fields. This is the same as on val2.png screenshot attached by original poster.

                    What should I do to add new rows to the TreeGrid so their fields get validated? I need the same functionality as startEditingNew() but with possibility to insert new row under some parent node.

                    Comment


                      #11
                      If you need the node at a particular spot, use addData() to create the new node with just a primaryKey and foreign key (so it appears in the right spot in the tree) then after it is saved (use callback from addData()) use setEditValues to apply values you want validated as though they were user input.

                      Comment


                        #12
                        I don't know primary key because it is assigned on the server side. Also I don't want to add empty records to the database.

                        Why it is not possible with grid.data.add()? In regular ListGrid, validation is performed on each record added with startEditingNew() function. And that works *before* data is submitted to the server.

                        Currently I tried this code, but it doesn't show validators:

                        Code:
                        var id = ... // id of the parent node
                        var parentNode = grid.data.findById(id);
                        
                        var treeNode = grid.data.add({parentId:id}, parentNode);
                        var rowNum = grid.getRecordIndex(treeNode);
                        newValues.parentId = id;
                        grid.setEditValues(rowNum, newValues);

                        Comment


                          #13
                          You can use just add() but the new node will always be at the end of the dataset. This is because of how complex it would be to do paging when the client is trying to keep track of newly added rows that the server doesn't know about.

                          Comment


                            #14
                            Originally posted by Isomorphic
                            You can use just add() but the new node will always be at the end of the dataset. This is because of how complex it would be to do paging when the client is trying to keep track of newly added rows that the server doesn't know about.
                            Are you referring to ListGrid? I specifically changed my code to use TreeGrid but it still doesn't work. Btw. I do not use paging.

                            Originally posted by Reference page, on TreeGrid.startEditingNew()
                            This inherited ListGrid API is not supported by the TreeGrid since adding a new tree node arbitrarily at the end of the tree is usually not useful. Instead, to add a new tree node and begin editing it, use either of these two strategies:

                            1. add a new node to the client-side Tree model via Tree.add(), then use startEditing to begin editing this node. Note that if using a DataSource, when the node is saved, an "update" operation will be used since adding a node directly to the client-side ResultTree effectively means a new node has been added server side.

                            2. use DataSource.addData() to immediately save a new node. Automatic cache sync by the ResultTree will cause the node to be integrated into the tree. When the callback to addData() fires, locate the new node by matching primary key and call startEditing to begin editing it.
                            I was able to add nodes to ListGrid group before I switched to TreeGrid. Now I did both of the above strategies and I am able to add nodes under parent node I want. But it is not the core problem.

                            The problem was there with ListGrid and with TreeGrid is still there. Validators do not work properly. This is definitely a bug! I'm stuck with this issue for more than a month now...

                            I'm adding nodes where I want but VALIDATORS do not show up.

                            Recently I tried this code:

                            Code:
                                    ds.addData(newRecord, function(dsResponse, data, dsRequest) {
                                        var obj = grid.data.findById(newRecord.id);
                                        var rowNum = grid.getRecordIndex(obj);
                                        grid.setEditValues(rowNum, newRecord);
                                        grid.validateRow(rowNum);
                                    });
                            Your advice on setEditValues didn't work. Only two methods setEditValues and validateRow used simultaneously made validators to actually show up. But that's not the end... When I double click on some empty cell and then exit the editor *LEAVING EMPTY VALUE* then ALL validators on all fields DISSAPEAR!

                            I'm enough frustrated with this... Please add some nodes with invalidate fields to treegrid and see it for yourself.

                            Comment


                              #15
                              This is not an unusual use case and we use this approach routinely. Something is wrong in your code, and if you want help with it, you should put together minimal code that we can run to see one of the problems you're having.

                              Comment

                              Working...
                              X