Skip to main content

How to Stop a Button Being Selected Twice While It Saves in Power Apps

· 7 min read
Jagdish Kumawat
Founder @ Dewiride

Saving to SharePoint takes a moment, and a second tap on Save in that moment runs its formula again: two items instead of one. Make setting a context variable the first thing OnSelect does, keep the button disabled and showing Saving... while the variable is true, and set it back when the save finishes, whether it worked or not.

The example is the Overtime Timesheet app's Log overtime screen. Each save creates an overtime entry, and a duplicate entry could get the same hours paid twice.

Prerequisites​

Step 1: Set the Variable First​

The first line of the button's OnSelect:

btnSaveLO → OnSelect (first line)
UpdateContext({locIsSaving: true});

Formulas joined with ; run one after the other, so the variable is true before the save starts. The loc prefix is a naming habit for context variables, which belong to one screen.

Step 2: Disable the Button While It's True​

The button's DisplayMode starts with !locIsSaving, so it's Disabled while a save runs. The rest of the formula checks the form is complete (How to Validate a Form Without an Edit Form in Power Apps):

btnSaveLO → DisplayMode
If(
!locIsSaving &&
!IsBlank(dpWorkDateLO.SelectedDate) &&
!IsBlank(cmbStartLO.Selected) &&
!IsBlank(cmbEndLO.Selected) &&
!IsBlank(cmbDepartmentLO.Selected) &&
!IsBlank(Trim(txtReasonLO.Text)) &&
IsBlank(lblProblemLO.Text),
DisplayMode.Edit,
DisplayMode.Disabled
)

The DisplayMode property of btnSaveLO in the expanded formula bar, starting with If(!locIsSaving && followed by the checks on each field and the problem label, returning DisplayMode.Edit or DisplayMode.Disabled

Step 3: Say What's Happening​

A disabled button with no explanation looks broken. The button's Text says what it's doing:

btnSaveLO → Text
If(locIsSaving, "Saving...", "Save")

The Text property of btnSaveLO with If(locIsSaving, "Saving...", "Save"), and the preview strip reading Save with Data type text

In Preview, while an entry was being saved, the button showed Saving... and was disabled:

The bottom of the Log overtime screen during a save: the reason Covered the evening handover while the department was a nurse short, 68 of 500 characters, and a greyed-out button reading Saving...

Step 4: Set It Back on Both Paths​

IfError has one path for a failed save and one for a successful save, and each sets the variable back to false:

btnSaveLO → OnSelect
UpdateContext({locIsSaving: true});
With(
{
Starts: ShiftStart(dpWorkDateLO.SelectedDate, cmbStartLO.Selected.Value),
Ends: ShiftEnd(dpWorkDateLO.SelectedDate, cmbStartLO.Selected.Value, cmbEndLO.Selected.Value)
},
IfError(
Patch(
OvertimeEntries,
Defaults(OvertimeEntries),
{
WorkDate: dpWorkDateLO.SelectedDate,
StartTime: Starts,
EndTime: Ends,
BreakMinutes: numBreakLO.Value,
Hours: Round((DateDiff(Starts, Ends, TimeUnit.Minutes) - numBreakLO.Value) / 60, 2),
DepartmentId: cmbDepartmentLO.Selected.ID,
Department: cmbDepartmentLO.Selected.Department,
Reason: Trim(txtReasonLO.Text),
EmployeeName: MyProfile.displayName,
EmployeeEmail: MyEmail,
Status: {Value: "Pending"},
WorkMonth: Text(dpWorkDateLO.SelectedDate, "yyyy-mm")
}
),
UpdateContext({locIsSaving: false});
Notify("Your overtime wasn't saved. " & FirstError.Message, NotificationType.Error),
UpdateContext({locIsSaving: false});
Notify("Your overtime was saved. It's waiting for approval.", NotificationType.Success);
Back()
)
)

In the formula bar:

The start of the OnSelect property of btnSaveLO in the expanded formula bar: UpdateContext setting locIsSaving to true, then With computing Starts and Ends, IfError around Patch to OvertimeEntries with Defaults and the record of columns, and UpdateContext setting locIsSaving to false

Step 5: Clear It When the Screen Opens​

Microsoft's UpdateContext page: a context variable holds its value until the app is closed, even when the user switches to a different screen. So the screen's OnVisible sets it to false each time the screen opens, before resetting the fields (How to Run a Formula When a Screen Opens in Power Apps with OnVisible):

Log Overtime Screen → OnVisible
UpdateContext({locIsSaving: false});
Reset(dpWorkDateLO);
Reset(cmbStartLO);
Reset(cmbEndLO);
Reset(numBreakLO);
Reset(cmbDepartmentLO);
Reset(txtReasonLO)

The OnVisible property of the Log Overtime Screen in the expanded formula bar: UpdateContext setting locIsSaving to false, then Reset for the date picker, both time combo boxes, the break, the department and the reason

Common Mistakes​

MistakeWhat happensDo this instead
Setting the variable after PatchThe button stays enabled while the save runsSet it on the first line
Setting it back only after a successful saveAfter a failed save, the button stays disabled and says Saving...Set it back on the error path too
Disabling the button without changing its textPeople think the app has stopped workingIf(locIsSaving, "Saving...", "Save")
A global variable (Set) for one screen's saveAny screen can change itA context variable, with UpdateContext

Troubleshooting​

SymptomLikely causeFix
The button says Saving... after an errorThe error path doesn't set the variable backAdd UpdateContext({locIsSaving: false}) to the IfError fallback
Save is disabled when the screen opens againThe variable kept its value from last timeSet it to false in OnVisible
Two entries saved from one formThe DisplayMode doesn't check the variable, or the variable is set after PatchCheck both

FAQ​

Does Back() wait for the save to finish?​

Back is in the success path of IfError, which runs once Patch has returned the saved record. In the example, the success message appeared and the app returned to the Home screen after each save.

Is the button enough to stop duplicates?​

It stops the double tap. The app also refuses a shift that overlaps one already logged: How to Check for Overlapping Times in Power Apps.

Conclusion​

Set a context variable on the first line of OnSelect, disable the button and show Saving... while it's true, set it back on both the success and error paths, and clear it in OnVisible. One tap, one entry.

Additional Resources​