
Using ngModel with input and textarea
Open workout-component.html and look for ngModel. It has been applied to form elements that allow user data input. These include input, textarea, and select. The workout name input setup looks like this:
<input type="text" name="workoutName" class="form-control" id="workout-name" placeholder="Enter workout name. Must be unique." [(ngModel)]="workout.name">
The preceding [(ngModel)] directive sets up a two-way binding between the input control and the workout.name model property. The brackets and parentheses should each look familiar. Previously, we used them separately from each other: the [] brackets for property binding and the () parentheses for event binding. In the latter case, we usually bound the event to a call to a method in the component associated with the template. You can see an example of this in the form with the button that a user clicks on to remove an exercise:
<span class="btn float-right trashcan" (click)="removeExercise(exercisePlan)"><span class="ion-ios-trash-outline"></span></span>
Here, the click event is explicitly bound to a method called removeExercise in our Workout component class. But for the workout.name input, we do not have an explicit binding to a method on the component. So what's going on here and how does the update happen without us calling a method on the component? The answer to that question is that the combination [( )] is shorthand for both binding a model property to the input element and wiring up an event that updates the model.
Put differently, if we reference a model element in our form, ngModel is smart enough to know that what we want to do is update that element (workout.name here) when a user enters or changes the data in the input field to which it is bound. Under the hood, Angular creates an update method similar to what we would otherwise have to write ourselves. Nice! This approach keeps us from having to write repetitive code to update our model.
Angular supports most of the HTML5 input types, including text, number, select, radio, and checkbox. This means binding between a model and any of these input types just works out of the box.
The textarea element works the same as the input:
<textarea name="description" . . . [(ngModel)]="workout.description"></textarea>
Here, we bind textarea to workout.description. Under the hood, ngModel updates the workout description in our model with every change we type into the text area.
To test out how this works, why don't we verify this binding? Add a model interpolation expression at the end of any of the linked inputs, such as this one:
<input type="text". . . [(ngModel)]="workout.name">{{workout.name}}
Open the Workout page, type something in the input, and see how the interpolation is updated instantaneously. The magic of two-way binding!
