Basic Form Validation with AngularJS and Bootstrap

PUBLISHED ON NOV 28, 2015 — ANGULARJS, BOOTSTRAP

Following on from my previous post, I’m going to cover adding some basic client side validation to the form we created.

We’ll start with the fullName input, so add the required tag to the input element like this:

<input type="text" id="fullName" name="fullName" class="form-control"
           placeholder="Enter your full name" ng-model="accountDetails.name" required/>

We’ve now stated that this input needs to have a value in order for our form to be valid. However, if you run the form you can leave the input blank and click submit, and the form will still close as though the data is fine, so we’ll stop that happening.

Go to the formController.js and to our submitForm function. In here, we just want to return without closing the form if the form is invalid, like so:

$scope.submitForm = function () {

    if ($scope.modalForm.$invalid) {
        return;
    }
    $modalInstance.close();
}

Now if you run the form, leave the input blank, and click the submit button, you’ll see that the form no longer closes.

However, this isn’t much use to the user as they get no information as to why nothing is happening, so let’s add that validation to the fullName input.

Back on formTemplate.html we want to modify the div around the fullName input to show something is wrong, we can do this using the bootstrap has-error class, and the ng-class directive to determine whether this class is applied or not.

We want this class to be active when the input is invalid, so now the div looks like this:

<div class="col-sm-9" ng-class="{'has-error' : modalForm.fullName.$invalid}">
      <input type="text" id="fullName" name="fullName" class="form-control"
             placeholder="Enter your full name" ng-model="accountDetails.name" required/>
  
</div>

This gives us a nice red border around the input to highlight there’s an error when nothing has been entered in the input. However, this shows as an error when the user first enters the form which might confuse some people.

So we only want the error formatting to be applied once the user has modified the control, we can do that using the $touched:

<div class="col-sm-9"
  ng-class="{'has-error' : modalForm.fullName.$invalid && modalForm.fullName.$touched}">
    <input type="text" id="fullName" name="fullName" class="form-control"
       placeholder="Enter your full name" ng-model="accountDetails.name" required/>
</div>

Now when you run the form, the error formatting will only be applied when you enter text in the input and then delete it, or if you enter the input and then move to another element without entering text.

The error is now highlighted, but it still isn’t clear to the user what the issue is, so let’s add a message to the form that informs the user of what the problem is. To do this, we want to add a span underneath our input with the message, like so:

<div class="col-sm-9"
  ng-class="{'has-error' : modalForm.fullName.$invalid && modalForm.fullName.$touched}">
        <input type="text" id="fullName" name="fullName" class="form-control"
   placeholder="Enter your full name" ng-model="accountDetails.name" required/>
        <span class="help-block">Full name is required</span>
</div>

I’ve added the help-block class to the span which gives us the font colouring and some padding all courteously from Bootstrap, but the problem we have is that it’s currently always shown, so we want to modify the span so it’s only visible when the error formatting on the input is being shown. We can achieve this using ng-show and the same condition that’s on the input, so the div will now look like this:

<div class="col-sm-9"
 ng-class="{'has-error' : modalForm.fullName.$invalid && modalForm.fullName.$touched}">
       <input type="text" id="fullName" name="fullName" class="form-control"
           placeholder="Enter your full name" ng-model="accountDetails.name" required/>
       <span class="help-block"
           ng-show="modalForm.fullName.$invalid && modalForm.fullName.$touched">
           Full name is required</span>
</div>

Now the message is displayed along with the formatting, but only when appropriate!

A problem we still have with the form is that if the user tries to submit the form before touching the input, it’s still not clear to the user what the problem is. We can fix this by using $submitted on the class of the div and the show of the span, like this:

<div class="col-sm-9"
    ng-class="{'has-error' : modalForm.$submitted || modalForm.fullName.$invalid &&
            modalForm.fullName.$touched}">
        <input type="text" id="fullName" name="fullName" class="form-control"
            placeholder="Enter your full name" ng-model="accountDetails.name" required/>
        <span class="help-block"
            ng-show="modalForm.$submitted || modalForm.fullName.$invalid &&
                modalForm.fullName.$touched">Full name is required</span>
</div>

Now when you try and submit the form without entering data the validation is applied and the user can see the errors, whilst the existing validation still works. This is only one input, but the principle is the same for others so you can expand and change the validation principles as you see fit.

You can now be sure that the data from your form is populated as you see fit, but there’s still a chance that something could go wrong with the submission of data regardless, for example on a log in form where the password is wrong. We’ll need a way of displaying this to the user, so we’ll hook up the submit form functionality to a fake function which you would replace with a call to your api.

So in formController add another function, I’ve called it fakeApiCall. Have it accept a name parameter, and return true when it’s a specified hard coded value, or false otherwise. My function looks like this:

$scope.fakeApiCall = function (name)
{
    if (name === "Rufio") {
        return true;
    } else {
        return false;
    }
}

We’ll also need a variable on the scope adding, this will be used to bind to our error notifications visibility, which I called submitError.

Now we just need to call this in our submitForm function, and when it returns true we close the form, otherwise we set submitError to true, so the submitForm function now looks like this:

$scope.submitForm = function () {
    if ($scope.modalForm.$invalid) {
        return;
    }

    if ($scope.fakeApiCall($scope.accountDetails.name)) {
        $modalInstance.close();
    } else {
        $scope.submitError = true;
    }
}

Now we need to add the notification to the form so it can be displayed. This is provided by Bootstrap making it easy to implement, so add it to the top of your form:

<div class="alert alert-danger" role="alert" ng-show="submitError">
        <strong>Woops, something went wrong!</strong>
</div>

If you run this now you’ll see the form looks as normal, however if you submit the data with something other than your hardcoded value (in my case Rufio) then you’ll see a red notification box displayed at the top of your form. The last thing I did here was to make this notification dismissable. Again, this is personal preference, but it’s easy enough to implement.

Again, functionality is provided by Bootstrap, so you just need to add a button in the notifications div, and modify the class to mark it as a dismissable alert, so you end up with this:

<div class="alert alert-danger alert-dismissible" role="alert" ng-show="submitError">
          <button type="button" class="close" data-dismiss="alert" aria-label="Close">
             <span aria-hidden="true">*</span>
          </button>
          <strong>Woops, something went wrong!</strong>
</div>

However, if you run this you’ll see that the dismiss button actually has no effect. This is because the functionality is provided by the bootstrap.js script which we haven’t included in this project, so we need to add this in our index.html file. You’ll also need to include jQuery as the bootstrap.js script depends on it. So add those two scripts, with jQuery being the first of the two to prevent errors, and your index.html head section will now look like this:

<head>
    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <script src="Scripts/angular.min.js"></script>
    <script src="Scripts/angular-ui/ui-bootstrap-tpls.min.js"></script>
    <script src="Scripts/angular-route.min.js"></script>
    <script src="app/ModalDialogsApp.js"></script>
    <script src="app/HomeController.js"></script>
    <script src="app/ModalForm/formController.js"></script>
    <script src="Scripts/jquery-1.9.1.min.js"></script>
    <script src="Scripts/bootstrap.min.js"></script>
    <title></title>
</head>

And that’s the basics of client side form validation with AngularJS and Bootstrap! Just expand these principles to cover the rest of your form how you see fit, and replace the fake function and ones similar to actual calls to your API and you’re good to go.

comments powered by Disqus