Skip to main content
May 3, 2021
Question

Invalid index when adding an additional value

  • May 3, 2021
  • 5 replies
  • 0 views

Hello everyone,

I am building an interface dynamically for a questionnaire based on previous responses (so I can view the previous answers and then edit them if necessary when re-reviewing). The questions are stored in one database, the items being assessed in another, and the responses to my questions in a third. So, the issue is when I add a new question and answer, I receive the following error:

Interface Definition: Expression evaluation error at function a!forEach [line 140]: Error in a!forEach() expression during iteration 25: Expression evaluation error at function a!radioButtonField [line 145]: Invalid index (25) for list: valid range is 1..24

It reads as though it's able to loop through my first 24 questions and then throws up on the new entry, but I am not constraining the index to 24 values. I believe this is because it's not handling the missing values properly (previously assessed items have no response for the new question) so I manually inserted the values into a test database and received the same error. I've copied the relevant code below and I'm hoping it's something obvious that I've simply overlooked. Any help would be much appreciated!

a!localVariables(
  /*constants*/
  local!datetime:rule!Current_Date(),
  local!user:rule!Current_LoggedInUser(),
  local!nulls: index(
    rule!qryrefernceQuestionByplatformId(
      platformI_appianId: ri!platforms.appian_id
    ).data,
    wherecontains(
      "",
      touniformstring(
        index(
          rule!qryrefernceQuestionByplatformId(
            platformI_appianId: ri!platforms.appian_id
          ).data,
          "questionOrder",
          1
        )
      )
    ),
    "questionid",
    null
  ),
  local!refereceResponse: todatasubset(
    remove(
      rule!qryrefernceQuestionByplatformId(
        platformI_appianId: ri!platforms.appian_id
      ).data,
      wherecontains(
        "",
        touniformstring(
          index(
            rule!qryrefernceQuestionByplatformId(
              platformI_appianId: ri!platforms.appian_id
            ).data,
            "questionOrder",
            1
          )
        )
      )
    ),
    a!pagingInfo(1, - 1)
  ),
  local!temp,
  local!indexforQuestions: wherecontains(
    tointeger(local!nulls),
    tointeger(
      index(
        rule!QryGetQuestionsGeneral().data,
        "questionid",
        null
      )
    )
  ),
  local!questions: if(
    or(
      isnull(local!indexforQuestions),
      count(local!indexforQuestions) = 0
    ),
    rule!QryGetQuestionsGeneral(),
    todatasubset(
      remove(
        rule!QryGetQuestionsGeneral().data,
        local!indexforQuestions
      ),
      a!pagingInfo(1, - 1)
    )
  ),
  local!radioOptions: { "Yes", "No" },
  local!nQuestions: count(local!questions.data),
  /*datasubset*/
  local!currentPlatformID: if(
    rule!APN_isBlank(ri!currentPlatformID),
    ri!platforms.appian_id,
    ri!currentPlatformID
  ),
  local!newreferenceResponse: /*if(*/
  /*rule!APN_isBlank(*/
  /*local!refereceResponse.data*/
  /*),*/
  a!forEach(
    items: enumerate(local!nQuestions) + 1,
    expression: 'type!{urn:com:appian:types}QUESTION'(
      questionid: fv!index,
      platformid: ri!platforms.appian_id,
      temp: false
    )
  ),
  local!blankIntAns: if(
    rule!APN_isBlank(local!refereceResponse),
    {},
    wherecontains(
      "",
      touniformstring(
        index(local!refereceResponse.data, "answer", 1)
      )
    )
  ),
  local!initalGridData: if(
    length(local!blankIntAns) > 0,
    remove(
      local!refereceResponse.data,
      tointeger(local!blankIntAns)
    ),
    local!refereceResponse.data
  ),
  {
    a!cardLayout(
      contents: a!gridField(
        label: "",
        labelPosition: "ABOVE",
        data: /*local!refereceResponse.data,     */
        local!initalGridData,
        columns: {
          a!gridColumn(
            label: "Questions",
            value: rule!QryGetQuestionsGeneralByquestionId(fv!row.questionid).data.questiontext[1]
          ),
          a!gridColumn(label: "Response", value: fv!row.answer)
        },
        pagesize: 25,
        showWhen: and(
          local!refereceResponse.totalCount <> 0,
          not(ri!platformEdit = true)
        ),
        validations: {}
      ),
      height: "TALL",
      showWhen: and(
        local!refereceResponse.totalCount <> 0,
        not(ri!platformEdit = true)
      ),
      style: "STANDARD"
    ),
    a!cardLayout(
      contents: a!columnsLayout(
        columns: {
          a!columnLayout(
            contents: {
              a!forEach(
                items: local!questions.data,
                expression: {
                  if(
                    fv!item.format = "Y/N",
                    a!radioButtonField(
                      label: fv!item.questiontext,
                      labelPosition: "ABOVE",
                      choiceLabels: local!radioOptions,
                      choiceValues: local!radioOptions,
                      value: ri!newreferenceResponse[fv!index].answer,
                      saveInto: {
                        ri!newreferenceResponse[fv!index].answer,
                        if(
                          ri!newreferenceResponse[fv!index].answer = "No",
                          {
                            a!save(local!temp, fv!index),
                            a!forEach(
                              a!forEach(
                                local!questions.data,
                                if(
                                  fv!item.refToParent = tostring(local!temp),
                                  fv!item.questionOrder,
                                  {}
                                )
                              ),
                              a!save(
                                ri!newreferenceResponse[fv!item].answer,
                                Null
                              )
                            )
                          },
                          {}
                        ),
                        /*a!save(local!temp,a!forEach(local!questions.data,if(fv!item.refToParent="2",fv!item.id,{}))),*/
                        a!save(
                          ri!newreferenceResponse[fv!index].questionid,
                          fv!item.questionid
                        ),
                        a!save(
                          ri!newreferenceResponse[fv!index].temp,
                          ""
                        ),
                        a!save(
                          ri!newreferenceResponse[fv!index].isActive,
                          fv!item.isActive
                        ),
                        a!save(
                          ri!newreferenceResponse[fv!index].questionOrder,
                          fv!item.questionOrder
                        ),
                        a!save(
                          ri!newreferenceResponse.user,
                          local!user
                        ),
                        a!save(
                          ri!newreferenceResponse[fv!index].datetime,
                          local!datetime
                        ),
                        a!save(
                          ri!newreferenceResponse,
                          ri!newreferenceResponse
                        )
                      },
                      showWhen: if(
                        fv!item.levelIndicator = "2",
                        if(
                          ri!newreferenceResponse[tointeger(fv!item.refToParent)].answer = "Yes",
                          true,
                          false
                        ),
                        true()
                      ),
                      required: if(
                        fv!item.levelIndicator = "2",
                        if(
                          ri!newreferenceResponse[tointeger(fv!item.refToParent)].answer = "Yes",
                          true,
                          false
                        ),
                        true()
                      ),
                      choiceLayout: "STACKED",
                      validations: {}
                    ),
                    a!textField(
                      label: fv!item.questiontext,
                      labelPosition: "ABOVE",
                      value: ri!newreferenceResponse[fv!item.questionOrder].answer,
                      saveInto: {
                        ri!newreferenceResponse[fv!item.questionOrder].answer,
                        a!save(
                          ri!newreferenceResponse[fv!index].questionid,
                          fv!item.questionid
                        ),
                        a!save(
                          ri!newreferenceResponse[fv!index].temp,
                          ""
                        ),
                        a!save(
                          ri!newreferenceResponse[fv!index].isActive,
                          fv!item.isActive
                        ),
                        a!save(
                          ri!newreferenceResponse[fv!index].questionOrder,
                          fv!item.questionOrder
                        ),
                        a!save(
                          ri!newreferenceResponse.user,
                          local!user
                        ),
                        a!save(
                          ri!newreferenceResponse[fv!index].datetime,
                          local!datetime
                        ),
                        a!save(
                          ri!newreferenceResponse,
                          ri!newreferenceResponse
                        )
                      },
                      showWhen: if(
                        fv!item.levelIndicator = "2",
                        if(
                          ri!newreferenceResponse[tointeger(fv!item.refToParent)].answer = "Yes",
                          true,
                          false
                        ),
                        true()
                      ),
                      required: if(
                        fv!item.levelIndicator = "2",
                        if(
                          ri!newreferenceResponse[tointeger(fv!item.refToParent)].answer = "Yes",
                          true,
                          false
                        ),
                        true()
                      )
                    )
                  )
                }
              )
            }
          )
        },
        showWhen: or(
          local!refereceResponse.totalCount = 0,
          ri!platformEdit = true
        )
      ),
      height: "TALL",
      showWhen: or(
        local!refereceResponse.totalCount = 0,
        ri!platformEdit = true
      ),
      style: "STANDARD"
    )
  }
)

    5 replies

    mikes0011
    Brainy
    May 3, 2021

    You mentioned this error happens when you add a new question/answer, but I don't see any place in your code where such addition is handled.  When doing this addition, are you also adding a corresponding item to the end of the `ri!newreferenceResponse` array?  The error indicates that its length is not matching the length of local!questions.

    I notice that local!newreferenceResponse *does* appear to be configured to follow the length of local!questions by local variable "update chaining" as i call it, but of course this is completely separate from ri!newreferenceResponse.

    The Expression Guru
    May 4, 2021

    Thanks, Mike.

    I suppose that information would have been helpful. The questions aren't added in Appian (I don't have an interface built for it yet) so they are added manually to the database. Hopefully I can explain this a bit better, but the way the process works is:

    1. An asset is entered and the questions answered as applicable to that asset (static questions, mostly Yes/No)

    2. Responses are recorded in another table

    3. When the asset is re-assessed, Appian first puts together the list of questions and responses as they were entered the last time

    4. If nothing has changed I can simply submit the page and keep moving through the workflow. If it has changed, I change the questionnaire to provide the edited information, then submit

    I suspect the issue is between steps 3-4 where the question I added was not included in the previous assessment, but when I inserted responses in the DB it still errored with the same index issue.

    Does that help?

    mikes0011
    Brainy
    May 4, 2021

    I believe the solution requires that you do some initial formatting on the "answers" array - either prior to your user input task, or (maybe preferably) in your local variable definitions.  In the latter case, you'd want to save directly into the value of your local variable response array, rather than saving directly into the rule input as you're currently attempting; then upon click of the "submit" button, you'd push the value of the local variable back into the rule input.

    In either case the logic would be simply something like this: loop through the list of questions; look in the existing responses array for the current index.  If the index exists, keep the response at that index.  Otherwise if the index doesn't exist (i.e. you have 15 questions but only 14 extant responses, and we're now at index 15 of the questions array), declare a blank / default array entry of the "response" type.  Then when you try direct reference to a "newReferenceResponse" entry (i.e. "ri!newReferenceResponse[fv!index]"), it should no longer break.

    The Expression Guru