Skip to Content
TutorialFeature ModulesForm DraftsManual Draft Saving for Forms

Manual Draft Saving for Forms

Demo Project

https://editor.momen.app/tool/X57jbwZwmMV/WEB?code=bV7jVSBmP7Ko5&ref=0562398

Introduction

  • Goal: Build a form system where users can save incomplete data as drafts and resume editing later before final submission.
  • Core Logic: Use a status field (Draft / Submitted / Deleted) to track each record’s state, and a page variable form_id to control the UI mode: -1 means creating a new record, any other value means editing an existing draft.
  • Use Cases: Job applications, insurance claim forms, multi-page questionnaires, or any workflow where users may need to return later to complete their input.

Steps

This tutorial uses pre-styled layout blocks from the “Common UI Presets” template page. These preset elements provide basic styling and layout only; they contain no conditional logic, data bindings, or Actionflows. You can copy them directly to skip manual styling and focus on the core logic.

Setup

Data Model

Table: form — stores draft and submitted records.

Field NameTypeNote
idBigintAuto-generated, unique identifier (system column)
created_atTimestampAuto-generated (system column)
updated_atTimestampAuto-generated (system column)
statusTextForm state: Draft, Submitted, or Deleted
field_1TextCustom business field
field_2BigintCustom business field
account_idBigintForeign key linking to the account table

Page Entry Logic

  1. In the left sidebar, click the Pages tab and add a page named Page Form Drafts.
  2. Drag a Button onto the canvas. Change the button text to Create and rename the component to Button Create.
  3. Select Button Create and add an action under OnClick.
  4. Configure the logic flow:
    • Add a Condition node.
    • Case: Guest — If getIsLoggedIn is Is false, add a Show toast action: Please log in first.
    • Case: Logged In — Add an Open custom modal node targeting Modal Fill Form.

The modal is the workspace for filling out forms. A page variable tracks whether the user is creating a new record or editing an existing draft.

  1. Click the Modal tab in the left sidebar and create a modal named Modal Fill Form.
  2. Select the root container of Modal Fill Form, go to the Data tab in the right sidebar, and click + next to Variable.
  3. Set Name to form_id, Type to Bigint, and Default value to -1.

form_id controls the form mode. -1 means “Create Mode”. When an existing draft is loaded, this variable holds the actual record ID, switching the form to “Edit Mode”.

  1. Drag two Text Input components onto the modal canvas:
    • Rename the first input to Input Field 1 and set its type to Text.
    • Rename the second input to Input Field 2 and set its type to Bigint.

  1. Select the Button Cancel component. Under its OnClick configuration, add a Close modal node and set Scope to Close top.


Draft List & Actions

Draft List Components

Now that the modal is configured, return to the main page to build the draft list. The list will show all drafts belonging to the logged-in user.

  1. Select the Text Current number of drafts component. Bind its Content to Logged in user/form/Count and add a local filter: status Equal to 'Draft'.

Logged in user/form/Count is evaluated when user data loads or refreshes. The draft list uses the Subscription request type, which automatically keeps the UI in sync with database changes.

  1. Drag a List component onto the canvas and rename it to List Drafts. Set its Data source to the form table and toggle Request type to Subscription for real-time syncing.

  1. Open the Query criteria panel for the list and add two filter rules combined with an And operator:
    • account_id Equal to Logged in user/id
    • status Equal to 'Draft'

Interactive View Toggles

The draft list is placed inside a conditional view container that can be expanded or collapsed.

  1. Select Button Drafts inside the Case Closed state of the Conditional View Drafts container.
  2. Add a Switch conditional view action under its OnClick event. Target Conditional View Drafts and set Switch to Case Extended.

  1. Switch the container to Case Extended, select its internal Button Drafts, and add a Switch conditional view action under its OnClick event, setting the target back to Case Closed.

Save as Draft Actionflow

The “Save as Draft” logic validates that at least one field is filled, then inserts a new draft record and updates the form_id variable so the user can continue editing.

  1. Select Button Save as Draft.

  1. Add a Condition node for input validation:
    • Name the branch Case: Input Empty and use the And operator.
    • Rule: Input Field 1/Value Is null And Input Field 2/Value Is null.
    • Add a Show toast node inside this branch: Please fill in at least one field.

  1. In the Case: Input Not Empty branch, add an Insert form node:
    • Target Table: form.
    • Parameters: Set status to Draft. Bind field_1 to Input Field 1/Value and field_2 to Input Field 2/Value. Bind account_id to Logged in user/id.

  1. After the Insert form node, add a Set variable node:
    • Scope: Page and component
    • Target Variable: form_id
    • Value: Bind to Action result/Insert form/id
  2. Add a Show toast node: Draft saved successfully.

Submitting the Form

The “Apply” button determines whether to insert a new submitted record or update an existing draft, based on the form_id variable.

  1. Select Button Apply and enter its OnClick action flow.
  2. Add an input validation check using the same logic as the draft phase (at least one field must be filled). Under the Case: Input Not Empty branch, add a nested Condition node.

  1. Name the branch Case: New Submission and set the expression: Modal Fill Form/Variable/form_id Equal to -1.

  1. Path 1: New Submission (form_id == -1):
    • Add an Insert form node targeting the form table. Set status to Submitted and map the input fields to their corresponding database columns.

  1. Path 2: Update Existing Draft to Submitted (form_id != -1):
    • Add an Update form node targeting the form table.
    • Query criteria: id Equal to Modal Fill Form/Variable/form_id.
    • Parameters: Set status to Submitted. Sync business fields with current input values (Input Field 1/Value and Input Field 2/Value).
    • Append a success toast (Submission successful) and close the modal.

Delete Confirmation Modal

To prevent accidental deletion, a separate confirmation modal is used to pass the user’s decision back to the calling Actionflow.

  1. Create a new modal named Modal Confirm Delete. Go to the Data tab in the right sidebar and create:
    • An Output parameter named is_deleted (Boolean) — this will be returned to the caller.
    • A local Variable also named is_deleted (Boolean) — this tracks which button the user clicks inside the modal.

  1. Select the modal root, go to the Outputs panel, and configure a Condition tree:
    • Case 0: If local variable is_deleted Is true, pass True to the Output.
    • Case 1: If local variable is_deleted Is false, pass False to the Output.

  1. Select Button NO. On its OnClick event, add a Set variable node to set is_deleted to False, followed by a Close modal (Close top) node.

  1. Select Button YES. On its OnClick event, add a Set variable node to set is_deleted to True, followed by a Close modal (Close top) node.

Record Deletion

The deletion logic checks whether the draft being deleted is currently loaded in the form, and shows a confirmation modal only if it is.

  1. Select the Text Delete component inside the list item row and open its OnClick event flow.
  2. Add a Condition node at the start:
    • Case: Active Draft — Test if Modal Fill Form/Variable/form_id Equal to List/Data source/Current item/id.

  1. Path 1: Delete the draft currently open in the form (requires confirmation):
    • Add an Open custom modal node targeting Modal Confirm Delete.
    • In the On Modal Closed callback, add a Condition node.
    • Case: Confirm Delete — Check if the output variable Modal/Modal Confirm Delete/is_deleted is Is true.

  • If true, add an Update form node. Query criteria: id Equal to List/Data source/Current item/id. Set status to Deleted.

  • Add a Set variable node. Scope: Page and component. Set form_id back to -1 to reset the form to Create Mode.
  • Add a success toast: Draft successfully deleted.

  1. Path 2: Delete a draft that is not currently open (no confirmation):
    • In the Case: Inactive Draft branch, add an immediate Update form node. Query criteria: id Equal to List/Data source/Current item/id. Set status to Deleted.
    • Add a success toast: Draft successfully deleted.

The draft is soft-deleted (status = Deleted) and remains in the database. The list uses Subscription, so the UI updates automatically when the record changes.

Loading a Draft into the Form

The “Apply” link loads a draft’s data back into the form inputs and sets the form_id variable so the user can continue editing.

  1. Select the Text Apply link inside the list row template.
  2. Under its OnClick event, add a Set variable node. Target form_id and set its value to List/Data source/Current item/id.
  3. Add two Set input value nodes to load data back into the UI fields:
    • Target Input Field 1 and set its value to List/Data source/Current item/field_1.
    • Target Input Field 2 and set its value to List/Data source/Current item/field_2.

Verification

Step 1: Login Required Test

  • Click the Preview icon in the top navigation bar to open the development sandbox.
  • Use the simulator toolbar at the base of the screen and click Restore user to logged out state to clear the session.
  • Click the main page Create button.
  • Expected Result: The form modal stays closed. A warning toast appears: Please log in first.
  • Now log in using the Login simulation panel on the lower action bar — select the simulated user role Logged-in User.

Step 2: Create a New Draft

  • Click the Create button again.
  • Expected Result: Modal Fill Form opens with form_id = -1.
  • Enter text in Input Field 1 and a number in Input Field 2.
  • Click Save as Draft.
  • Expected Result: A success toast appears: Draft saved successfully. The draft list updates and a new record appears. The form_id is now set to the new record’s ID (e.g., 1).

Step 3: Save a Second Draft

  • Change the values in the input fields.
  • Click Save as Draft again.
  • Expand the draft list by clicking the Drafts toggle.
  • Expected Result: The draft list now shows two items. The count reads: Current number of drafts: 2.

Step 4: Load a Draft, Then Delete It

  • Click the Apply link on the first draft row (ID 1).
  • Expected Result: The input fields are populated with the values from draft 1.
  • Click the Delete link on the same row.
  • Expected Result: Because this draft is currently open in the form, the Modal Confirm Delete confirmation dialog appears.
  • Click YES.
  • Expected Result: The modal closes. The form_id resets to -1. The draft no longer appears in the list. The draft count decreases by one.

Step 5: Delete a Draft That Is Not Currently Open (If you have multiple drafts)

  • Create a new draft (any values) and save it. Note its ID.
  • Click Apply on a different draft (not the one you just created) to load it into the form.
  • In the draft list, click Delete on the draft you just created (the one that is not currently loaded).
  • Expected Result: The draft is deleted immediately (no confirmation dialog). The form_id remains unchanged (still pointing to the draft you loaded). The list updates and the count decreases.

Step 6: Switch Between Drafts (If you have multiple drafts)

  • Create two drafts (Draft A and Draft B).
  • Click Apply on Draft A. Verify that form_id becomes A’s ID and the inputs are populated with A’s values.
  • Without saving or deleting, click Apply on Draft B.
  • Expected Result: The inputs now show B’s values. The form_id has switched to B’s ID. Draft A remains in the list unchanged.
Last updated on