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

  • Try removing the validationGroup in the a!dateField() and keep only on button or  buttonWidget- . My CE site is down so could not try validate but this change could work 

  • 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.

  • 0
    Certified Senior Developer
    in reply to Mike Schmitt

    I am compleetly with Mike Schmitt there.
    The benefit of the validationGroup functionality depends strongly on your use case. 

    "Validations" are evaluated instantly. valdiationGroup is more focusing on "validate true" parameter of an buttonWidget.
    This means mostly a focus on required fields.

    Check out the following approaches:


    ValidationMessages:
    -> Validation Message - Appian 21.3


    R
    equired Messages:
    Configure Buttons with Conditional Requiredness - Appian 21.3

  • 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
            )
          }
        ),
    
      )
    )