Complete Guide to Displaying Validation Error Messages on Form Submission in AngularJS

Nov 24, 2025 · Programming · 4 views · 7.8

Keywords: AngularJS | Form Validation | Error Messages

Abstract: This article provides an in-depth exploration of two core methods for displaying validation error messages upon form submission in AngularJS. By analyzing the working principles of $dirty state and $submitted property, it详细介绍介绍了traditional scope variable approach and the native support in Angular 1.3+. The article includes complete code examples, implementation steps, and best practice recommendations to help developers build more user-friendly form validation experiences.

Fundamentals of Form Validation

In AngularJS, form validation is a crucial component for building user-friendly interfaces. When users input data into forms, AngularJS automatically tracks state changes for each form control, including validity, dirty status, and more. However, by default, validation error messages typically only display after users interact with the form (i.e., when controls become "dirty").

Limitations of Traditional Methods

In earlier versions of AngularJS, developers commonly used expressions like ng-show="frmRegister.first_name.$dirty && frmRegister.first_name.$error.required" to control the display of error messages. This approach relies on the control's $dirty state, meaning validation errors only appear after users have actually modified form fields.

The limitation of this design is evident: when users click the submit button without any prior interaction with the form, since all controls remain in a "pristine" state, even if validation errors exist, error messages won't display. This results in poor user experience, as users cannot immediately understand the specific reasons for form submission failure.

Scope Variable Solution

To address this issue, the community proposed an effective solution: introducing a scope variable to track form submission status. The specific implementation steps are as follows:

First, define a submitted variable in the controller:

app.controller('FormController', function($scope) {
    $scope.submitted = false;
    
    $scope.register = function() {
        $scope.submitted = true;
        
        // If the form is valid, proceed with submission logic
        if ($scope.frmRegister.$valid) {
            // Execute registration logic
            $scope.registered = true;
        }
    };
});

Then, modify the validation expressions in the HTML template:

<form name="frmRegister" ng-submit="register();" novalidate>
    <div>
        <input placeholder="First Name" name="first_name" type="text" ng-model="user.firstName" required />
        <span ng-show="submitted && frmRegister.first_name.$error.required">First Name is required</span>
    </div>
    <div>
        <input placeholder="Last Name" name="last_name" type="text" ng-model="user.lastName" required />
        <span ng-show="submitted && frmRegister.last_name.$error.required">Last Name is required</span>
    </div>
    <div>
        <input placeholder="Email" name="email" type="email" ng-model="user.email" required />
        <span ng-show="submitted && frmRegister.email.$error.required">Email is required.</span>
        <span ng-show="submitted && frmRegister.email.$error.email">Invalid Email address.</span>
    </div>
    <input type="submit" value="Save" />
    <span ng-show="registered">YOU ARE NOW REGISTERED USER</span>
</form>

Native Support in Angular 1.3+

Starting from AngularJS version 1.3, the framework natively provides a more elegant solution. The form object now includes a $submitted property, which is automatically set to true when the form is submitted.

Implementation using the native $submitted property:

<form name="frmRegister" ng-submit="register();" novalidate>
    <div>
        <input placeholder="First Name" name="first_name" type="text" ng-model="user.firstName" required />
        <span ng-show="frmRegister.$submitted && frmRegister.first_name.$error.required">First Name is required</span>
    </div>
    <div>
        <input placeholder="Last Name" name="last_name" type="text" ng-model="user.lastName" required />
        <span ng-show="frmRegister.$submitted && frmRegister.last_name.$error.required">Last Name is required</span>
    </div>
    <div>
        <input placeholder="Email" name="email" type="email" ng-model="user.email" required />
        <span ng-show="frmRegister.$submitted && frmRegister.email.$error.required">Email is required.</span>
        <span ng-show="frmRegister.$submitted && frmRegister.email.$error.email">Invalid Email address.</span>
    </div>
    <input type="submit" value="Save" />
</form>

Implementation Details Analysis

Both methods share similar core logic but differ in implementation mechanisms:

Scope Variable Method:

Native $submitted Method:

Best Practice Recommendations

In practical development, it's recommended to choose the appropriate solution based on project requirements:

  1. If using AngularJS 1.3+, prioritize the native $submitted property
  2. For projects requiring backward compatibility, use the scope variable method
  3. Consider combining both methods for better user experience, displaying errors during both interaction and submission
  4. Ensure error messages are clearly visible with appropriate CSS styling

Extended Application Scenarios

Beyond basic required field validation, this pattern can be extended to more complex validation scenarios:

By properly applying these techniques, developers can build both aesthetically pleasing and practical form validation systems that significantly enhance user experience.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.