Lately I have been creating a lot of forms — administration applications just tend to have plenty of them. Obviously one of the most important topics I needed to solve is how to efficiently handle whatever server has to say about my beautiful model that I am sending to that beast.

Simple API error handling with global error and field error visible

Angular is great with forms having all those custom directives to handle validation and ng-messages to show errors as they come in (although lately I personally use custom directive based on ng-messages). But at some point you need to send all of that data to the server and a lot of bad things can happen. Depending on your application you can have 100% of server side validation replicated on Frontend, which is great, but often there are some checks that will be done just when you send the whole thing. Whatever is the case, your API will eventually send you a “not 200" response that you need to handle. More importantly, you need to give user feedback what happened.

Requirements

When planning for api error handling I decided that I need to cover several use cases:

I need to show general api errors in given place in form (e.g. top of the form). This is when something happens and we don’t really know what (server failed) I need to show field related error next to the field as I would show standard validation error. I need to show some errors in general area that are field related but that field is not found in form. I want to be able to decide if particular form field should have error attached to that field or should it fall into “general error” area.

Use Case 1 and Use Case 2 for simple API error handling

I believe 1 and 2 are easy to understand but some explanation is needed for number 3 and 4.

Why number 3? Sometimes you are adding some data to request that is not explicitly editable by user inside form (hidden fields, some generated data). It can happen that this additional data is invalid. In such case we need to tell something meaningful to the user. Even if it is to contact administrator etc.

Use Case 3 and Use Case 4 for simple error handling

Why 4? This might be my custom requirement but I needed to be able to decide if particular form field is considered an “API field” and should get all errors delivered to that field $error. This solution assumes that field need to be consciously declared as “aware of api errors” to get those delivered.

Form validation and API errors

Frontend validators are cool. We know what happens, we know how to fix it. Angular comes in and gives us all those helpers like $valid, $invalid etc. But it is not so easy when handling API error. We do not necessarily know what is the reason error occurred just from response and we are not prepared to call any validation mechanism that could tell us when it got fixed. Error happened, user should read the message and act accordingly. We will just try not to get in user’s way.

To enable that we definitely do not want to block re-sending the form if we cannot say when user fixed issue. For that reason let’s divide API errors into 2 groups:

Do not invalidate form at all (save button should be enabled)— use cases 1, 2 and 4 Invalidate one field model (save button gets disabled)— use case 3

What it means is that if there is any type of general error not connected to any form field or the field is not found in form or not marked as “API error aware”, do not invalidate anything. If there is an API error for existing field and that field tells us that it wants to handle API errors, then apply that error to the field resulting in $invalid state for field model.

Direct result of those requirements is the need to implement proper mechanism to take in API error connected to the field and then remove it as user attempts to fix this error.

Planning solution

If you create a simple AngularJS application you might have created a controller that exposes function like “ctrl.save()” that sends the data and possibly handles error in promise failure block like:

This works ok for small applications but we need something more complex and a bit more automated and obvious from HTML perspective. For this we create following components:

api-form directive — it should be declared next to “form” or “ng-form” and will automatically attach logic to that form controller. api-validate directive — it should be declared next to ng-model on particular field to indicate that this field is “server error aware”. Plus it will hold logic on when to remove error. It will expose “$registerApiError” interface on ng-model to handle API errors related with the field. ApiFormValidationService — service used to implement all the logic needed by this solution.

The goal is that by just adding “api-form” to any of our forms it will automatically start handling errors for us:

<form name="myForm" api-form>

<input type="text" name="fieldName" ng-model="fieldModel"/>

</form>

To have an error attached to the field errors, we just add api-validate directive next to it’s ng-model:

<form name="myForm" api-form>

<input type="text" name="fieldName" ng-model="fieldModel" api-validate/>

</form>

Of course we need to be able to show general errors for my form so I need to extend formController with some custom parameters — we will add $api object to it. This object will hold basic information similar to the form itself but exposing what backend knows about this form. All fields in this object should work similarly how you expect them to work in standard form:

$api: {

$valid: true,

$invalid: false,

$error: null

}

For the sake of this post let’s assume that backend is responding with this kind of structures when having error: