Submit button not working as I expect

Hi all, 

I have an interface that displays an editable grid - representing a timesheet and the days of the week - Monday to Friday. The interface is part of a site. The idea is, an employee can enter their start time, finish time, lunch break etc and that data will be sent to a database when the user clicks the submit button. They can keep doing this as many times as they want and the data should stay consistent as the user clicks the submit button. The problem is, this doesn't happen. After clicking the submit button, the data is sent to the database correctly but the grid is populated with the default values instead of the values I just set. The correct, database values will only be displayed if I refresh the browser.

My theory is that when I click the submit button, the process (which updates the database) fires and before it can finish, the page reloads with default data because it couldn't find anything in the database. Is my theory correct? If so, what can be done? If not, what am I missing? I don't want to tell the user they have to refresh the browser to see their changes.

Here is my code for the interface:

load(
  local!headerCells: {
    a!gridLayoutHeaderCell(
      label: "Day"
    ),
    a!gridLayoutHeaderCell(
      label: "Start",
      align: "CENTER"
    ),
    a!gridLayoutHeaderCell(
      label: "Finish",
      align: "CENTER"
    ),
    a!gridLayoutHeaderCell(
      label: "Total",
      align: "CENTER"
    ),
    a!gridLayoutHeaderCell(
      label: "Lunch",
      align: "CENTER"
    ),
    a!gridLayoutHeaderCell(
      label: "Credits",
      align: "CENTER"
    ),
    a!gridLayoutHeaderCell(
      label: "Holiday and other paid leave",
      align: "CENTER"
    ),
    a!gridLayoutHeaderCell(
      label: "Net Hours",
      align: "CENTER"
    )
  },
  local!columnConfigs: {
    a!gridLayoutColumnConfig(
      weight: 3
    ),
    a!gridLayoutColumnConfig(
      weight: 1
    ),
    a!gridLayoutColumnConfig(
      weight: 1
    ),
    a!gridLayoutColumnConfig(
      weight: 1
    ),
    a!gridLayoutColumnConfig(
      weight: 1
    ),
    a!gridLayoutColumnConfig(
      weight: 1
    ),
    a!gridLayoutColumnConfig(
      weight: 8
    ),
    a!gridLayoutColumnConfig(
      weight: 1
    ),
    a!gridLayoutColumnConfig(
      width: "ICON"
    )
  },
  local!pagingInfo: a!pagingInfo(
    startIndex: 1,
    batchSize: - 1
  ),
  local!defaultTime: "00:00",
  local!defaultStartTime: "09:00",
  local!defaultFinishTime: "17:00",
  local!defaultLunch: "00:30",
  local!employeeId: user(
    loggedInUser(),
    "customField1"
  ),
  local!endOfWeekDate: rule!Flexi_Time_getEndOfWeekDate(
    today()
  ),
  /*Get all dates for selected week */
  local!selectedDateRange: rule!Flexi_Time_getWeekDateArray(
    local!endOfWeekDate
  ),
  /*Get Timesheet Id */
  local!timesheetId: rule!Flexi_Time_fetchTimesheetForEmployeeIdAndPeriodDates(
    employeeId: local!employeeId,
    startDate: rule!Flexi_Time_getTimesheetPeriodDates(
      local!selectedDateRange
    ).startDate,
    endDate: rule!Flexi_Time_getTimesheetPeriodDates(
      local!selectedDateRange
    ).endDate
  ).timesheetId,
  /*Get Workweek Id */
  local!workweekId: with(
    local!data: rule!Flexi_Time_getCombinedTimesheetField(
      local!employeeId,
      local!selectedDateRange,
      "workweekId"
    ),
    if(
      rule!APN_isEmpty(
        local!data
      ),
      null,
      local!data.workweekId
    )
  ),
  /*Determine if a timesheet needs to be created or if one already exists for current period */
  local!timesheetIsRequired: rule!Flexi_Time_requiresTimesheet(
    employeeId: local!employeeId,
    dates: local!selectedDateRange
  ),
  /*Determine if a workweek needs to be created */
  local!workweekIsRequired: rule!APN_isEmpty(
    local!workweekId
  ),
  /*Get all workdays that exist in DB for selected week, otherwise build empty/default ones */
  local!workdays: a!forEach(
    items: local!selectedDateRange,
    expression: with(
      local!workday: rule!Flexi_Time_getEmployeeWorkday(
        fv!item,
        local!employeeId
      ),
      if(
        rule!APN_isEmpty(
          local!workday.workdayId
        ),
        rule!Flexi_Time_buildEmptyWorkdayCDT(
          workweekId: local!workweekId,
          date: fv!item,
          startTime: local!defaultStartTime,
          finishTime: local!defaultFinishTime,
          lunch: local!defaultLunch
        ),
        local!workday
      )
    )
  ),

  a!formLayout(
    contents: {
      a!boxLayout(
        label: "Summary",
        contents: {},
        style: "INFO",
        marginBelow: "STANDARD"
      ),
      a!boxLayout(
        label: "Weekly Timesheets",
        contents: {
          a!sideBySideLayout(
            items: {
              a!sideBySideItem(
                item: a!richTextDisplayField(
                  value: a!richTextImage(
                    image: a!documentImage(
                      document: cons!FLEXI_TIME_LEFTARROWICON,
                      /*alternate appian icon: */
                      /*document: a!iconIndicator("MOVE_LEFT"), */
                      altText: "N/A",
                      caption: "View previous week",
                      link: a!dynamicLink(
                        saveInto: {
                          a!save(
                            local!endOfWeekDate,
                            local!endOfWeekDate - 7
                          ),
                          a!save(
                            local!selectedDateRange,
                            rule!Flexi_Time_getWeekDateArray(
                              local!endOfWeekDate
                            )
                          ),
                          a!save(
                            local!timesheetId,
                            rule!Flexi_Time_fetchTimesheetForEmployeeIdAndPeriodDates(
                              employeeId: local!employeeId,
                              startDate: rule!Flexi_Time_getTimesheetPeriodDates(
                                local!selectedDateRange
                              ).startDate,
                              endDate: rule!Flexi_Time_getTimesheetPeriodDates(
                                local!selectedDateRange
                              ).endDate
                            ).timesheetId
                          ),
                          a!save(
                            local!workweekId,
                            with(
                              local!data: rule!Flexi_Time_getCombinedTimesheetField(
                                local!employeeId,
                                local!selectedDateRange,
                                "workweekId"
                              ),
                              if(
                                rule!APN_isEmpty(
                                  local!data
                                ),
                                null,
                                local!data.workweekId
                              )
                            )
                          ),
                          a!save(
                            local!timesheetIsRequired,
                            rule!Flexi_Time_requiresTimesheet(
                              employeeId: local!employeeId,
                              dates: local!selectedDateRange
                            )
                          ),
                          a!save(
                            local!workweekIsRequired,
                            rule!APN_isEmpty(
                              local!workweekId
                            )
                          ),
                          a!forEach(
                            local!workdays,
                            a!save(
                              fv!item,
                              with(
                                local!workday: rule!Flexi_Time_getEmployeeWorkday(
                                  local!selectedDateRange[fv!index],
                                  local!employeeId
                                ),
                                if(
                                  rule!APN_isEmpty(
                                    local!workday.workdayId
                                  ),
                                  rule!Flexi_Time_buildEmptyWorkdayCDT(
                                    workweekId: local!workweekId,
                                    date: local!selectedDateRange[fv!index],
                                    startTime: local!defaultStartTime,
                                    finishTime: local!defaultFinishTime,
                                    lunch: local!defaultLunch
                                  ),
                                  local!workday
                                )
                              )
                            )
                          )
                        }
                      )
                    )
                  ),
                  align: "LEFT"
                )
              ),
              a!sideBySideItem(
                item: a!dateField(
                  label: "Week Ending",
                  labelPosition: "ADJACENT",
                  value: local!endOfWeekDate,
                  saveInto: {
                    a!save(
                      local!endOfWeekDate,
                      rule!Flexi_Time_getEndOfWeekDate(
                        save!value
                      )
                    ),
                    a!save(
                      local!selectedDateRange,
                      rule!Flexi_Time_getWeekDateArray(
                        local!endOfWeekDate
                      )
                    ),
                    a!save(
                      local!timesheetId,
                      rule!Flexi_Time_fetchTimesheetForEmployeeIdAndPeriodDates(
                        employeeId: local!employeeId,
                        startDate: rule!Flexi_Time_getTimesheetPeriodDates(
                          local!selectedDateRange
                        ).startDate,
                        endDate: rule!Flexi_Time_getTimesheetPeriodDates(
                          local!selectedDateRange
                        ).endDate
                      ).timesheetId
                    ),
                    a!save(
                      local!workweekId,
                      with(
                        local!data: rule!Flexi_Time_getCombinedTimesheetField(
                          local!employeeId,
                          local!selectedDateRange,
                          "workweekId"
                        ),
                        if(
                          rule!APN_isEmpty(
                            local!data
                          ),
                          null,
                          local!data.workweekId
                        )
                      )
                    ),
                    a!save(
                      local!timesheetIsRequired,
                      rule!Flexi_Time_requiresTimesheet(
                        employeeId: local!employeeId,
                        dates: local!selectedDateRange
                      )
                    ),
                    a!save(
                      local!workweekIsRequired,
                      rule!APN_isEmpty(
                        local!workweekId
                      )
                    ),
                    a!forEach(
                      local!workdays,
                      a!save(
                        fv!item,
                        with(
                          local!workday: rule!Flexi_Time_getEmployeeWorkday(
                            local!selectedDateRange[fv!index],
                            local!employeeId
                          ),
                          if(
                            rule!APN_isEmpty(
                              local!workday.workdayId
                            ),
                            rule!Flexi_Time_buildEmptyWorkdayCDT(
                              workweekId: local!workweekId,
                              date: local!selectedDateRange[fv!index],
                              startTime: local!defaultStartTime,
                              finishTime: local!defaultFinishTime,
                              lunch: local!defaultLunch
                            ),
                            local!workday
                          )
                        )
                      )
                    )
                  },
                  align: "CENTER"
                )
              ),
              a!sideBySideItem(
                item: a!richTextDisplayField(
                  value: a!richTextImage(
                    image: a!documentImage(
                      document: cons!FLEXI_TIME_RIGHTARROWICON,
                      /*alternate appian icon: */
                      /*document: a!iconIndicator("MOVE_RIGHT"), */
                      altText: "N/A",
                      caption: "View next week",
                      link: a!dynamicLink(
                        saveInto: {
                          a!save(
                            local!endOfWeekDate,
                            local!endOfWeekDate + 7
                          ),
                          a!save(
                            local!selectedDateRange,
                            rule!Flexi_Time_getWeekDateArray(
                              local!endOfWeekDate
                            )
                          ),
                          a!save(
                            local!timesheetId,
                            rule!Flexi_Time_fetchTimesheetForEmployeeIdAndPeriodDates(
                              employeeId: local!employeeId,
                              startDate: rule!Flexi_Time_getTimesheetPeriodDates(
                                local!selectedDateRange
                              ).startDate,
                              endDate: rule!Flexi_Time_getTimesheetPeriodDates(
                                local!selectedDateRange
                              ).endDate
                            ).timesheetId
                          ),
                          a!save(
                            local!workweekId,
                            with(
                              local!data: rule!Flexi_Time_getCombinedTimesheetField(
                                local!employeeId,
                                local!selectedDateRange,
                                "workweekId"
                              ),
                              if(
                                rule!APN_isEmpty(
                                  local!data
                                ),
                                null,
                                local!data.workweekId
                              )
                            )
                          ),
                          a!save(
                            local!timesheetIsRequired,
                            rule!Flexi_Time_requiresTimesheet(
                              employeeId: local!employeeId,
                              dates: local!selectedDateRange
                            )
                          ),
                          a!save(
                            local!workweekIsRequired,
                            rule!APN_isEmpty(
                              local!workweekId
                            )
                          ),
                          a!forEach(
                            local!workdays,
                            a!save(
                              fv!item,
                              with(
                                local!workday: rule!Flexi_Time_getEmployeeWorkday(
                                  local!selectedDateRange[fv!index],
                                  local!employeeId
                                ),
                                if(
                                  rule!APN_isEmpty(
                                    local!workday.workdayId
                                  ),
                                  rule!Flexi_Time_buildEmptyWorkdayCDT(
                                    workweekId: local!workweekId,
                                    date: local!selectedDateRange[fv!index],
                                    startTime: local!defaultStartTime,
                                    finishTime: local!defaultFinishTime,
                                    lunch: local!defaultLunch
                                  ),
                                  local!workday
                                )
                              )
                            )
                          )
                        }
                      )
                    )
                  ),
                  align: "RIGHT"
                )
              )
            },
            alignVertical: "MIDDLE"
          ),
          a!gridLayout(
            headerCells: append(
              local!headerCells,
              a!gridLayoutHeaderCell(
                label: ""
              )
            ),
            columnConfigs: local!columnConfigs,
            rows: {
              a!forEach(
                local!workdays,
                rule!Flexi_Time_TimesheetGridRow(
                  dayOfWeek: rule!Flexi_Time_displayDayOfWeek(
                    local!selectedDateRange[fv!index]
                  ),
                  startTime: fv!item.startTime,
                  finishTime: fv!item.finishTime,
                  totalTime: fv!item.totalHours,
                  lunchTime: fv!item.lunch,
                  credits: fv!item.credits,
                  leave: fv!item.paidLeave,
                  netHours: fv!item.netHours
                )
              )
            }
          )
        },
        style: "INFO",
        marginBelow: "STANDARD"
      ),
      a!buttonLayout(
        primaryButtons: {
          a!buttonWidget(
            label: "SAVE WEEK",
            style: "PRIMARY",
            saveInto: {
              a!save(
                ri!workdays,
                local!workdays
              ),
              a!save(
                ri!workweekIsRequired,
                local!workweekIsRequired
              ),
              a!save(
                ri!timesheetIsRequired,
                local!timesheetIsRequired
              ),
              a!save(
                ri!workweekId,
                local!workweekId
              ),
              a!save(
                ri!timesheetId,
                local!timesheetId
              ),
              a!save(
                ri!selectedDateRange,
                local!selectedDateRange
              ),
              a!save(
                ri!employeeId,
                local!employeeId
              )
            },
            submit: true
          )
        }
      )
    }
  )
)

Thanks for your help Appian community!

  Discussion posts and replies are publicly visible

  • Hi Fabiant, 

    If you are writing the data in a process model asynchronously, then your theory is correct and as a remedy, do the below:

    1. Pass the same pv as value to the form from the process model.

    2. Instead of querying from the database on the load, check if the rule input(for which the value is passed from the process model) is null and then query it,else assign the rule input to the local. 

    Hope this helps

  • 0
    Certified Lead Developer

    Set default values into a PV, use the PV as your ACP for the user input task.  Configure the SavedValues output of your database write node to store the saved values into THAT PV.  Also set a boolean for another PV isDatabaseDoneWriting (or something like it) to true.

    Next, add a node that the process parks at until it either times out (after enough time to convince you the database write is clearly broken) or that PV comes true, then loop back into your user input task.  The trouble is, once the user input task starts, you can't change any of the variables it has without referencing the PVs directly in the SAIL and not passing through ACs, which isn't standard practice.  And even those won't update your SAIL unless your user interacts with something.  This means your form could have bad data preloaded, then jump suddenly to good data when the user clicks, which would be confusing and less than ideal experience.  Best to make sure you're operating on saved values and ensure that the write is done before you synch up.

    It might be better, depending on how long the write is, to make the DB write synchronous.  If you have other stuff you could be doing at the same time, you could have a parallel flow that comes to a Complex gate that requires both flows to finish before proceeding back to the user input task.  It could say "Working" for a noticably long time, but you'll have correct data when it refreshes.  If the "Working" isn't too long that would be a better experience.

  • I should have mentioned that my interface is the process start form. In any case, it's working now - it turns out all I had to do was chain the nodes together. Thanks everyone.

  • 0
    Certified Lead Developer

    Hi  as per my understanding, it's worth giving a try to the below mentioned solution approach:

    • Move your configuration from a Start Form to a User Input Task
    • Chain the DB nodes defined after the User Input Task (If you are not performing some heavy write / update operation which may consume more time, because this can break the chain)
    • Based on user action (such as Submit, Save & Review, Close) loop back your flow to the same user input task again and again
      • Assume, Submit button click will write/update the data into DB and terminates the process
      • Whereas Save & Review button click will write/update the data and loop your process flow back to the same User Input Task, so that the user can get the latest data and can review/start working on it

    I understand, when you have a Start Form then unless you do not submit, instance for that particular process won't be created, whereas in this case every single time user acts on an Action will trigger an instance of this process, irrespective of whether you submit the form or not.

    Also, you do have an another approach, i.e. by using a!writeToDataStoreEntity() or a!writeToMultipleDataStoreEntities() smart service function and invoking them on button click under it's saveInto, and after this smart service execution, you can reload the local variable(under the same saveInto) which was holding the data retrieved from the Database. In this case you can define submit:false for the button widget so that even after submit you will be on the same form. 

    Problem in this case: You will loose the trace, if something goes wrong while compared to the earlier approach. And also you may find some difficulty while dealing with the Parent Child (Primary - Foreign Key) relationship mapping.

    Hope this will help.