Post

Power Apps Dynamic Form Schema: Add Controls on the Fly

Power Apps Dynamic Form Schema: Add Controls on the Fly

TL;DR: Describe your form as data: one row per field with name, label, type, options and a required flag. A vertical gallery renders that table, each row holds one control per field type and shows only the matching one. On submit, ForAll(galForm.AllItems, ...) collects every answer, checks the required fields and saves the result as JSON. A new field is a new schema row, no new control in the app.

Every new question in a form normally means opening the app, adding a data card, publishing again. Reza Dorrani shows a different approach: the form structure lives in data, and the app draws the controls from it at run time.

🎥 Video Tutorial

💡 Challenge

The Edit form control is bound to the columns of one data source. A checklist that differs per department, a survey that changes every month, or an onboarding form with optional sections all need fields that aren’t known when you build the app.

✅ Solution

Separate structure from layout. A schema table lists the fields, a gallery turns each schema row into a label plus the right input control, and a submit formula reads all control values from the gallery’s AllItems property.

🔧 How It’s Done

1. Define the schema.

🔸 For a first test, a collection in the screen’s OnVisible:

1
2
3
4
5
6
7
ClearCollect(
    colFormSchema,
    { Order: 1, Field: "FullName",    Label: "Full name",      Type: "Text",     Required: true,  Options: "" },
    { Order: 2, Field: "Department",  Label: "Department",     Type: "Dropdown", Required: true,  Options: "Sales;Finance;IT" },
    { Order: 3, Field: "StartDate",   Label: "Start date",     Type: "Date",     Required: false, Options: "" },
    { Order: 4, Field: "NeedsLaptop", Label: "Needs a laptop", Type: "Toggle",   Required: false, Options: "" }
)

🔸 In production, keep the same columns in a SharePoint list or Dataverse table and load it with ClearCollect(colFormSchema, FormSchema). Business users can then add fields without touching the app.

2. Render the schema with a gallery.

🔸 Insert a Blank vertical gallery named galForm, Items:

1
Sort(colFormSchema, Order)

🔸 In the template, add a label lblField and one input control per type, stacked on the same position:

Control Visible Other properties
lblField true Text: ThisItem.Label & If(ThisItem.Required, " *", "")
txtValue (Text input) ThisItem.Type = "Text"  
ddValue (Drop down) ThisItem.Type = "Dropdown" Items: Split(ThisItem.Options, ";"), AllowEmptySelection: true
dpValue (Date picker) ThisItem.Type = "Date"  
tglValue (Toggle) ThisItem.Type = "Toggle"  

Split returns a single-column table with the column Value, so the drop down shows the options directly. AllowEmptySelection keeps the drop down empty until the user picks a value, otherwise it preselects the first option and the required check in step 4 never fails.

3. Collect the answers.

🔸 Submit button, OnSelect:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Set(
    varAnswers,
    ForAll(
        galForm.AllItems,
        {
            Field: ThisRecord.Field,
            Required: ThisRecord.Required,
            Answer: Switch(
                ThisRecord.Type,
                "Text", txtValue.Text,
                "Dropdown", ddValue.Selected.Value,
                "Date", Text(dpValue.SelectedDate, "yyyy-mm-dd"),
                "Toggle", If(tglValue.Value, "true", "false")
            )
        }
    )
);

Inside ForAll over AllItems, the control names refer to the controls of the current gallery row, so every row returns its own value.

4. Validate and save.

1
2
3
4
5
6
7
8
9
10
If(
    CountRows(Filter(varAnswers, Required && IsBlank(Answer))) > 0,
    Notify("Please fill in all required fields.", NotificationType.Error),
    Patch(
        FormSubmissions,
        Defaults(FormSubmissions),
        { Title: User().Email, Answers: JSON(varAnswers) }
    );
    Notify("Saved.", NotificationType.Success)
)

🔸 FormSubmissions is a list or table with a multiple-lines-of-text column Answers. Because the answers are stored as JSON, new fields need no new column.

5. Add a field on the fly.

🔸 Add a row to the schema, for example { Order: 5, Field: "Phone", Label: "Phone", Type: "Text", Required: false, Options: "" }. The gallery shows it on the next load, the submit formula picks it up without changes.

🎉 Result

One screen renders any form that the schema describes. Fields, order, required flags and drop-down options change in data, and every submission is saved as one JSON document with exactly the fields the user saw.

🌟 Key Advantages

🔸 No republish for new fields: the structure lives in a list or table.

🔸 One screen, many forms: filter the schema by form name and reuse the same gallery.

🔸 Built-in validation: the required flag comes from the schema too.

🔸 Stable storage: one JSON column instead of a column per question.

⚠️ Good to Know

🔸 Reporting. JSON answers are flexible but harder to filter in views. If you need to report on single fields, write the answers additionally to a child table with one row per field (Patch inside a ForAll over varAnswers).

🔸 New control types (number, multi-select, attachments) need one more control in the gallery template and one more branch in the Switch.

🛠️ FAQ

1. Why not use the Edit form control?

The Edit form is bound to the columns of one data source. A schema-driven gallery can show fields that don’t exist as columns and changes without editing the app.

2. How do I prefill an existing submission?

Parse the stored JSON with ParseJSON, look up the answer per field and set the controls’ Default property, for example txtValue.Default = the answer for ThisItem.Field.

3. Does the gallery need a fixed row height?

No. Use a Blank flexible height gallery if fields need different heights, for example a multi-line text input.

4. How do I handle the Tab order?

See Tip 84 below. Controls in a gallery need extra care for keyboard navigation.

🔸 #PowerPlatformTip 80: ‘Rapid Dynamic Forms with AI’ - generate the schema behind this approach automatically with AI instead of hand-writing it.

🔸 #PowerPlatformTip 84: ‘Tabbing in Dynamic Forms’ - fix the Tab-key order once your gallery-based form is rendering controls dynamically.

Microsoft Learn: Gallery control · ForAll function · JSON function


This technique was shared by Reza Dorrani, a Microsoft MVP and Power Platform expert. Video Credit: Reza Dorrani

This tip is by Marcel Lehmann, Microsoft MVP (Business Applications) and founder of the Power Platform Academy – live Power Platform workshops, free or CHF 49. Join the workshop waitlist to get notified about new dates. For companies that want this implemented for them, see KMUpower – Power Platform consulting & automation for SMEs (DACH).

This post is licensed under CC BY 4.0 by the author.

Microsoft and the Power Platform product names (for example Power Apps, Power Automate, Copilot Studio) are trademarks of the Microsoft group of companies. This is an independent website. It is not operated, sponsored or endorsed by Microsoft.