
Custom validation messages for an exercise
A workout without any exercise is of no use. There should at least be one exercise in the workout and we should validate this restriction.
The problem with exercise count validation is that it is not something that the user inputs directly and the framework validates. Nonetheless, we still want a mechanism to validate the exercise count in a manner similar to other validations on this form.
What we will do is add a hidden input box to the form that contains the count of the exercises. We will then bind this to ngModel and add a pattern validator that will check to make sure that there is more than one exercise. We will set the value of the input box to the count of the exercises:
<input type="hidden" name="exerciseCount" #exerciseCount="ngModel" ngControl="exerciseCount" class="form-control" id="exercise-count" [(ngModel)]="workout.exercises.length" pattern="[1-9][0-9]*">
Then, we will attach a validation message to it similar to what we just did with our other validators:
<label *ngIf="exerciseCount.control.hasError('pattern')" class="alert alert-danger extended-validation-message">The workout should have at least one exercise!</label>
We are not using ngModel in its true sense here. There is no two-way binding involved. We are only interested in using it to do custom validation.
Open the new Workout page, add an exercise, and remove it; we should see this error:

What we did here could have been easily done without involving any model validation infrastructure. But, by hooking our validation into that infrastructure, we do derive some benefits. We can now determine errors with a specific model and errors with the overall form in a consistent and familiar manner. Most importantly, if our validation fails here, the entire form will be invalidated.
Implementing custom validation the way we just did is not what you would want to do very often. Instead, it will usually make more sense to implement this kind of complicated logic inside a custom directive. We'll cover creating custom directives in detail in Chapter 4, Angular Directives in Depth.
One nuisance with our newly implemented Exercise Count validation is that it shows when the screen for a new Workout first appears. With this message, we are not able to use ng-touched to hide the display. This is because the exercises are being added programmatically and the hidden input we are using to track their count never changes from untouched as exercises are added or removed.
To fix this problem, we need an additional value to check when the state of the exercise list has been reduced to zero, except when the form is first loaded. The only way that situation can happen is if the user adds and then removes exercises from a workout to the point that there are no more exercises. So, we'll add another property to our component that we can use to track whether the remove method has been called. We call that value removeTouched and set its initial value to false:
removeTouched: boolean = false;
Then, in the remove method we will set that value to true:
removeExercise(exercisePlan: ExercisePlan) { this.removeTouched = true; this.workoutBuilderService.removeExercise(exercisePlan); }
Next, we will add removeTouched to our validation message conditions, like so:
<label *ngIf="exerciseCount.control.hasError('pattern') && (removeTouched)"
Now, when we open a new workout screen, the validation message will not display. But if the user adds and then removes all the exercises, then it will display.
To understand how model validation rolls up into form validation, we need to understand what form-level validation has to offer. However, even before that, we need to implement saving the workout and calling it from the workout form.