Validation Group is not working properly

I have added validation group in a datefield and added the same on a button. But the validation is triggered instantly on change of dates. My requirement is to validate the date field which is added in a grid layout on click of a button. 

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    Personally I've always found ValidationGroup functionality to be unintuitive and cumbersome to implement, use, and/or test, with results that are inconsistent with expectations or designed intentions.  Thus I typically use other methods to enforce validations under certain circumstances, beginning with making sure my forms are scope-limited where possible, and also, abstracting certain form functionality using local variables (such as variables keeping track of validation status of certain elements if needed).  Without knowing a bit more detail about your particular requirement or intended design, it's hard to offer much more of a concrete suggestion than this.

  • Thanks Mike. The use case was to validate a date against the other date only on form submission. The validation group does not give the desired result for my use case. I have used a local variable to set a flag based on the validation on submit, and added validations based on this local variable in the date fields. Now it works. 

  • 0
    Certified Lead Developer
    in reply to Sharmila Nagaraj

    Cool, thanks for confirming - it sounds like you've figured out approximately what I was referring to then :)

  • Yes Mike. But I am facing one issue again. The validation works fine in the interface when I run it as stand alone, but not when I start the related action where This interface is added as a start form. 

    a!localVariables(
      local!testData: {
        {
          serialNumber: 1,
          date1: today(),
          date2: today() + 10
        },
        {
          serialNumber: 2,
          date1: today() + 10,
          date2: today() + 20
        },
        
      },
      local!isValidMcdDate: a!refreshVariable(
        value: a!forEach(local!testData, null),
        refreshAlways: false()
      ),
      a!formLayout(
        contents: {
          a!boxLayout(
            label: "Test Data",
            contents: a!gridLayout(
              emptyGridMessage: "No items available",
              headerCells: {
                a!gridLayoutHeaderCell(label: "Serial Number"),
                a!forEach(
                  items: local!testData,
                  expression: a!gridLayoutHeaderCell(label: fv!item.serialNumber)
                )
              },
              rows: {
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(
                      value: a!richTextItem_18r1(text: "Serial Number", )
                    ),
                    a!forEach(
                      local!testData,
                      a!tagField(
                        tags: a!tagItem(
                          text: fv!item.serialNumber,
                          textColor: "STANDARD"
                        )
                      )
                    )
                  }
                ),
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(value: a!richTextItem(text: "Date 1")),
                    a!forEach(
                      local!testData,
                      a!dateField(
                        label: "Date 1",
                        labelPosition: "ADJACENT",
                        value: fv!item.date1,
                        saveInto: fv!item.date1,
                        validations: if(local!isValidMcdDate[fv!index], "Error", "")
                      )
                    )
                  }
                ),
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(value: a!richTextItem(text: "Date 2")),
                    a!forEach(
                      local!testData,
                      a!dateField(
                        label: "Date 2",
                        labelPosition: "ADJACENT",
                        value: fv!item.date2,
                        saveInto: fv!item.date2,
                        
                      )
                    )
                  }
                ),
                
              }
            )
          )
        },
        buttons: a!buttonLayout(
          primaryButtons: {
            a!buttonWidget(
              label: "Submit",
              value: false,
              saveInto: {
                a!save(
                  local!isValidMcdDate,
                  a!forEach(
                    local!testData,
                    if(
                      todate(fv!item.date1) > todate(fv!item.date2),
                      true(),
                      null
                    )
                  )
                ),
                
              },
              submit: true,
              style: "PRIMARY",
              validate: true(),
              
            )
          },
          secondaryButtons: {
            a!buttonWidget(
              label: "Cancel",
              value: true,
              saveInto: ri!cancel,
              submit: true,
              style: "NORMAL",
              validate: false
            )
          }
        ),
        
      )
    )

    Appreciate your help.

  • 0
    Certified Lead Developer
    in reply to Sharmila Nagaraj

    Thanks for posting some generic code I could just copy into an interface editor, that's really helpful and I have it working on my environment now.  Could you talk a bit more about what exactly the validation is meant to do, and what you would like the end user's experience to be, step by step?  I see you're setting the validation local variable upon click of the Submit button, though i'm a little unclear why you're setting the value there instead of upon initial declaration and allowing the validation error to show up naturally as soon as the invalid data is entered.

  • There are two date fields where user can enter dates in any order. Date 1 should be greater than Date 2, but the requirement is Date 1 should not get validated until user enters/modifies date 2.This is why I am trying to validate the Date 1 on submit, thus allowing the user to enter dates in any order. If I set the 'validation' on Date 1, it fires immediately on tab out.

  • 0
    Certified Lead Developer
    in reply to Sharmila Nagaraj

    I believe you can handle such a condition on the declaration of your validation value instead of waiting until submit.  If you really need to wait until submit for certain issues, I always suggest using a!validationMessage() which has the option to only evaluate at form submit time [i've added a separate example of this which fires if one of the dates is left blank].

    Here is my suggested modification to your code which I'm hoping will hold off on showing validation errors until after both dates are entered:

    a!localVariables(
      local!testData: {
        {
          serialNumber: 1,
          date1: today(),
          date2: today() + 10
        },
        {
          serialNumber: 2,
          date1: today() + 10,
          date2: today() + 20
        },
    
      },
      local!columnHasDateValidationError: a!refreshVariable(
        value: a!forEach(
          local!testData,
          if(
            or(
              isnull(fv!item.date1),
              isnull(fv!item.date2)
            ),
            false(),
            todate(fv!item.date2) < todate(fv!item.date1)
          )
        ),
        refreshAlways: false()
      ),
      
      a!formLayout(
        contents: {
          a!boxLayout(
            label: "Test Data",
            contents: a!gridLayout(
              emptyGridMessage: "No items available",
              headerCells: {
                a!gridLayoutHeaderCell(label: "Serial Number"),
                a!forEach(
                  items: local!testData,
                  expression: a!gridLayoutHeaderCell(label: fv!item.serialNumber)
                )
              },
              rows: {
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(
                      value: a!richTextItem_18r1(text: "Serial Number", )
                    ),
                    a!forEach(
                      local!testData,
                      a!tagField(
                        tags: a!tagItem(
                          text: fv!item.serialNumber,
                          textColor: "STANDARD"
                        )
                      )
                    )
                  }
                ),
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(value: a!richTextItem(text: "Date 1")),
                    a!forEach(
                      local!testData,
                      a!dateField(
                        label: "Date 1",
                        labelPosition: "ADJACENT",
                        value: fv!item.date1,
                        saveInto: fv!item.date1,
                        validations: if(local!columnHasDateValidationError[fv!index], "Error: Date 2 must be greater than Date 1", "")
                      )
                    )
                  }
                ),
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(value: a!richTextItem(text: "Date 2")),
                    a!forEach(
                      local!testData,
                      a!dateField(
                        label: "Date 2",
                        labelPosition: "ADJACENT",
                        value: fv!item.date2,
                        saveInto: fv!item.date2,
    
                      )
                    )
                  }
                ),
    
              }
            )
          )
        },
        validations: {
          a!validationMessage(
            messagE: "All Dates must be populated.",
            validateAfter: "SUBMIT",
            showWhen: or(
              a!forEach(
                local!testData,
                or(
                  isnull(fv!item.date1),
                  isnull(fv!item.date2)
                )
              )
            )
          )
        },
        buttons: a!buttonLayout(
          primaryButtons: {
            a!buttonWidget(
              label: "Submit",
              value: "Submit",
              saveInto: {
                a!save(
                  ri!cancel,
                  false()
                )
                /*a!save(*/
                  /*local!isValidMcdDate,*/
                  /*a!forEach(*/
                    /*local!testData,*/
                    /*if(*/
                      /*todate(fv!item.date1) > todate(fv!item.date2),*/
                      /*true(),*/
                      /*null*/
                    /*)*/
                  /*)*/
                /*),*/
    
              },
              submit: true,
              style: "PRIMARY",
              validate: true(),
    
            )
          },
          secondaryButtons: {
            a!buttonWidget(
              label: "Cancel",
              value: true,
              saveInto: ri!cancel,
              submit: true,
              style: "NORMAL",
              validate: false
            )
          }
        ),
    
      )
    )

Reply
  • 0
    Certified Lead Developer
    in reply to Sharmila Nagaraj

    I believe you can handle such a condition on the declaration of your validation value instead of waiting until submit.  If you really need to wait until submit for certain issues, I always suggest using a!validationMessage() which has the option to only evaluate at form submit time [i've added a separate example of this which fires if one of the dates is left blank].

    Here is my suggested modification to your code which I'm hoping will hold off on showing validation errors until after both dates are entered:

    a!localVariables(
      local!testData: {
        {
          serialNumber: 1,
          date1: today(),
          date2: today() + 10
        },
        {
          serialNumber: 2,
          date1: today() + 10,
          date2: today() + 20
        },
    
      },
      local!columnHasDateValidationError: a!refreshVariable(
        value: a!forEach(
          local!testData,
          if(
            or(
              isnull(fv!item.date1),
              isnull(fv!item.date2)
            ),
            false(),
            todate(fv!item.date2) < todate(fv!item.date1)
          )
        ),
        refreshAlways: false()
      ),
      
      a!formLayout(
        contents: {
          a!boxLayout(
            label: "Test Data",
            contents: a!gridLayout(
              emptyGridMessage: "No items available",
              headerCells: {
                a!gridLayoutHeaderCell(label: "Serial Number"),
                a!forEach(
                  items: local!testData,
                  expression: a!gridLayoutHeaderCell(label: fv!item.serialNumber)
                )
              },
              rows: {
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(
                      value: a!richTextItem_18r1(text: "Serial Number", )
                    ),
                    a!forEach(
                      local!testData,
                      a!tagField(
                        tags: a!tagItem(
                          text: fv!item.serialNumber,
                          textColor: "STANDARD"
                        )
                      )
                    )
                  }
                ),
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(value: a!richTextItem(text: "Date 1")),
                    a!forEach(
                      local!testData,
                      a!dateField(
                        label: "Date 1",
                        labelPosition: "ADJACENT",
                        value: fv!item.date1,
                        saveInto: fv!item.date1,
                        validations: if(local!columnHasDateValidationError[fv!index], "Error: Date 2 must be greater than Date 1", "")
                      )
                    )
                  }
                ),
                a!gridRowLayout(
                  contents: {
                    a!richTextDisplayField(value: a!richTextItem(text: "Date 2")),
                    a!forEach(
                      local!testData,
                      a!dateField(
                        label: "Date 2",
                        labelPosition: "ADJACENT",
                        value: fv!item.date2,
                        saveInto: fv!item.date2,
    
                      )
                    )
                  }
                ),
    
              }
            )
          )
        },
        validations: {
          a!validationMessage(
            messagE: "All Dates must be populated.",
            validateAfter: "SUBMIT",
            showWhen: or(
              a!forEach(
                local!testData,
                or(
                  isnull(fv!item.date1),
                  isnull(fv!item.date2)
                )
              )
            )
          )
        },
        buttons: a!buttonLayout(
          primaryButtons: {
            a!buttonWidget(
              label: "Submit",
              value: "Submit",
              saveInto: {
                a!save(
                  ri!cancel,
                  false()
                )
                /*a!save(*/
                  /*local!isValidMcdDate,*/
                  /*a!forEach(*/
                    /*local!testData,*/
                    /*if(*/
                      /*todate(fv!item.date1) > todate(fv!item.date2),*/
                      /*true(),*/
                      /*null*/
                    /*)*/
                  /*)*/
                /*),*/
    
              },
              submit: true,
              style: "PRIMARY",
              validate: true(),
    
            )
          },
          secondaryButtons: {
            a!buttonWidget(
              label: "Cancel",
              value: true,
              saveInto: ri!cancel,
              submit: true,
              style: "NORMAL",
              validate: false
            )
          }
        ),
    
      )
    )

Children
No Data