Morten Sæther

← Blog

Episode 8: Forms and Data Collection

23 February 2026

Creating User-Friendly Forms that Balance Ease of Use with Data Quality

Introduction

Forms are the primary way external users interact with your data in Power Pages. Whether users are submitting support tickets, updating their profiles, or registering for events, forms must be intuitive, secure, and efficient. This episode teaches you how to create forms that encourage completion while maintaining data quality and security standards.

Key Concepts

Learning Objectives

By the end of this episode, you will be able to:

Why Good Form Design Matters

Poor form design is one of the primary reasons users abandon portal tasks. External users have less patience for confusing interfaces than internal users. A well-designed form can significantly improve user satisfaction and data quality while reducing support burden on your team.

Step-by-Step Guide

1. Planning Your Form Strategy

Before creating any form, consider:

Form Type Selection Guide:

2. Creating Your First Entity Form

Setting Up a Support Ticket Form:

  1. Navigate to Form Configuration:

    • Go to Portal Management → Entity Forms
    • Click New to create a new entity form
    • Set Name: “Customer Support Ticket”
    • Set Table: Case (incident)
  2. Configure Basic Settings:

    Mode: Insert
    Success Message: "Your support ticket has been submitted. Reference number: {ticketnumber}"
    Form Name: "Portal Case Form" (create this in Dataverse)
  3. Set Security Permissions:

    • Table Permissions: Create permission for authenticated users
    • Entity Form: Allow Create for Customer role
    • Validation: Ensure users can only create records assigned to them
  4. Add Form to Page:

    • Create or edit your support page
    • Add Entity Form component
    • Select your configured form

3. Designing User-Friendly Forms

Essential Form Usability Principles:

Progressive Disclosure:

// Example: Show additional fields based on issue type
function showAdditionalFields(issueType) {
    const techFields = document.getElementById('technical-fields');
    const billingFields = document.getElementById('billing-fields');
    
    // Hide all additional fields first
    techFields.style.display = 'none';
    billingFields.style.display = 'none';
    
    // Show relevant fields based on selection
    if (issueType === 'technical') {
        techFields.style.display = 'block';
    } else if (issueType === 'billing') {
        billingFields.style.display = 'block';
    }
}

Smart Defaults and Pre-population:

<!-- Example: Pre-populate user information -->
<script>
document.addEventListener('DOMContentLoaded', function() {
    // Pre-populate customer information
    document.getElementById('customerid').value = '{{ user.contactid }}';
    document.getElementById('emailaddress').value = '{{ user.emailaddress1 }}';
    document.getElementById('firstname').value = '{{ user.firstname }}';
    document.getElementById('lastname').value = '{{ user.lastname }}';
    
    // Set default priority and category
    document.getElementById('prioritycode').value = '2'; // Normal priority
    document.getElementById('casetypecode').value = '1'; // Question
});
</script>

Field Organization and Grouping:

4. Implementing Effective Validation

Client-Side Validation for Immediate Feedback:

// Example: Real-time email validation
function validateEmail(email) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    const emailField = document.getElementById('emailaddress');
    const errorDiv = document.getElementById('email-error');
    
    if (!emailRegex.test(email)) {
        emailField.classList.add('is-invalid');
        errorDiv.textContent = 'Please enter a valid email address';
        errorDiv.style.display = 'block';
        return false;
    } else {
        emailField.classList.remove('is-invalid');
        errorDiv.style.display = 'none';
        return true;
    }
}

// Example: Required field validation
function validateRequiredFields() {
    const requiredFields = document.querySelectorAll('[required]');
    let allValid = true;
    
    requiredFields.forEach(field => {
        if (!field.value.trim()) {
            field.classList.add('is-invalid');
            allValid = false;
        } else {
            field.classList.remove('is-invalid');
        }
    });
    
    return allValid;
}

Server-Side Validation Configuration:

5. Creating Multi-Step Forms with Web Forms

When to Use Web Forms:

Basic Web Form Setup:

  1. Create Web Form:

    • Go to Portal Management → Web Forms
    • Set Name: “Customer Registration Process”
    • Configure start step and success page
  2. Add Form Steps:

    • Step 1: Basic Information (contact details)
    • Step 2: Company Information (account details)
    • Step 3: Preferences and Settings
    • Step 4: Review and Submit
  3. Configure Step Logic:

    Condition: If user selects "Business Customer"
    Next Step: Company Information
    
    Condition: If user selects "Individual Customer"
    Next Step: Preferences and Settings

6. Advanced Form Features

File Upload Configuration:

<!-- Example: Secure file upload with restrictions -->
<div class="file-upload-section">
    <label for="attachment">Upload Supporting Documents</label>
    <input type="file" id="attachment" name="attachment" 
           accept=".pdf,.doc,.docx,.png,.jpg" 
           multiple 
           data-max-size="5242880"> <!-- 5MB limit -->
    <small class="form-text text-muted">
        Accepted formats: PDF, DOC, DOCX, PNG, JPG. Maximum size: 5MB per file.
    </small>
</div>

<script>
function validateFileUpload(input) {
    const maxSize = parseInt(input.dataset.maxSize);
    const allowedTypes = input.accept.split(',');
    
    Array.from(input.files).forEach(file => {
        // Check file size
        if (file.size > maxSize) {
            alert(`File ${file.name} is too large. Maximum size is 5MB.`);
            input.value = '';
            return;
        }
        
        // Check file type
        const fileExtension = '.' + file.name.split('.').pop().toLowerCase();
        if (!allowedTypes.includes(fileExtension)) {
            alert(`File type ${fileExtension} is not allowed.`);
            input.value = '';
            return;
        }
    });
}
</script>

Conditional Field Display:

// Example: Show different fields based on customer type
function handleCustomerTypeChange(customerType) {
    const businessFields = document.getElementById('business-customer-fields');
    const individualFields = document.getElementById('individual-customer-fields');
    
    if (customerType === 'business') {
        businessFields.style.display = 'block';
        individualFields.style.display = 'none';
        
        // Make business fields required
        businessFields.querySelectorAll('input, select').forEach(field => {
            field.required = true;
        });
        
        // Remove required from individual fields
        individualFields.querySelectorAll('input, select').forEach(field => {
            field.required = false;
        });
    } else {
        businessFields.style.display = 'none';
        individualFields.style.display = 'block';
        
        // Reverse the requirements
        businessFields.querySelectorAll('input, select').forEach(field => {
            field.required = false;
        });
        individualFields.querySelectorAll('input, select').forEach(field => {
            field.required = true;
        });
    }
}

Practical Example: Complete Support Ticket Form

Let’s build a comprehensive support ticket form for TechStart Solutions:

Form Structure:

  1. Customer Information (pre-populated):

    • Name, Email, Phone (read-only for authenticated users)
    • Account/Company (lookup to account record)
  2. Issue Details:

    • Issue Type (dropdown: Technical, Billing, General)
    • Priority (dropdown: Low, Normal, High)
    • Subject (required text field)
    • Description (rich text area)
  3. Technical Details (conditional, shown for technical issues):

    • Product/Service Affected (dropdown)
    • Error Messages (text area)
    • Steps to Reproduce (text area)
  4. Attachments:

    • File upload with validation
    • Multiple files allowed
    • Size and type restrictions

Form Validation Rules:

Security Configuration:

7. Form Performance and Mobile Optimization

Performance Best Practices:

Mobile-First Design:

/* Example: Mobile-optimized form styling */
.portal-form {
    max-width: 100%;
    padding: 1rem;
}

.form-group {
    margin-bottom: 1.5rem;
}

.form-control {
    font-size: 16px; /* Prevents zoom on iOS */
    padding: 12px;
    border-radius: 8px;
}

@media (max-width: 768px) {
    .form-row {
        flex-direction: column;
    }
    
    .form-col {
        width: 100%;
        margin-bottom: 1rem;
    }
    
    .btn {
        width: 100%;
        padding: 14px;
        font-size: 16px;
    }
}

Troubleshooting Common Form Issues

Problem: Form submissions create records but don’t redirect to success page Solution: Check entity form success settings and table permissions for redirect page

Problem: Validation messages don’t appear in the correct language Solution: Configure localized validation messages in form metadata

Problem: File uploads fail silently Solution: Check file size limits, allowed file types, and storage configuration

Problem: Users receive “Access Denied” when submitting forms Solution: Verify table permissions, entity form permissions, and user role assignments

Problem: Conditional logic doesn’t work on mobile devices Solution: Test JavaScript functionality across devices, ensure event handlers work with touch

Best Practices for Portal Forms

  1. User Experience First: Design forms from the user’s perspective, not the database structure
  2. Progressive Enhancement: Start with basic HTML forms, then add JavaScript enhancements
  3. Clear Error Messages: Tell users exactly what’s wrong and how to fix it
  4. Consistent Styling: Use your site’s design system for all form elements
  5. Accessibility: Ensure forms work with screen readers and keyboard navigation
  6. Security by Design: Validate everything server-side, never trust client-side validation alone
  7. Test Thoroughly: Test forms with real users on real devices with real data

Summary

Great forms feel effortless to users while collecting high-quality data for your organization. Focus on understanding your users’ goals, removing unnecessary friction, and providing clear feedback throughout the process. Remember that every field you add increases the chance of abandonment—be ruthless about what’s truly necessary.

In the next episode, you’ll learn how to provide rich information and functionality through detailed record pages that give users everything they need to accomplish their goals.