Angular forms with GitHub example — tutorial 3: form data binding


Ramin Ahmadi

Ramin AhmadiMay 10 · 7 min read

Forms are designed to serve a purpose and that usually means collecting and storing the data. In some cases, we might be interested in prepopulated forms where we pre-fill textboxes and pre-select checkboxes so that data entry would be more convenient. But when I say data in the context of an Angular app, it means a data model or model for short. The process to collect data from a form is called data binding. Angular has a handy directive that handles form called NgModel. In this tutorial, I’m going to teach you how to create a custom data model, and a form to collect data based on that. Finally, I’m going to show you how to use data binding to collect the data that user enters.

By adding FormsModule to our app.module earlier, we let Angular to handle forms and forms events for us so we won’t have to set watcher on each form and constantly watch every events that happens inside of it. If you don’t remember or started from this tutorial, please have a look at my first post where I talked about how to create a basic form. looking into html code generated by Angular, we can see how it uses NgForm directive controls our forms. Don’t worry about adding it to your #form, it’s an internal directive and Angular takes care of that for you.

Lets see how we can create a form with NgForm. I’m gonna add a directive called #detailsForm and set the value to ngForm. This will assign an instance of ngForm to detailsForm. Now we can use it simply by putting the directive inside a curly bracket. This is called interpolation and, in a nutshell, means embedding expression into a HTML text. In simple terms, it means if you use {{object}}, it prints the object value on the browser. And of course, if you use the object itself, you’d end up getting [object Object] printed.

To make it readable, we need to use json pipe like below line.

{{object | json}}

By printing #detailsForm on the page, we can see what kind of information it contains.

{ "submitted": false, "_directives": [], "ngSubmit": { "_isScalar": false, "observers": [], "closed": false, "isStopped": false, "hasError": false, "thrownError": null, "__isAsync": false }, "form": { "validator": null, "asyncValidator": null, "pristine": true, "touched": false, "_onDisabledChange": [], "controls": {}, "valueChanges": { "_isScalar": false, "observers": [], "closed": false, "isStopped": false, "hasError": false, "thrownError": null, "__isAsync": false }, "statusChanges": { "_isScalar": false, "observers": [], "closed": false, "isStopped": false, "hasError": false, "thrownError": null, "__isAsync": false }, "status": "VALID", "value": {}, "errors": null } }

GitHub code commit

To extract information form the form, we are going to use ngModel. It creates an instance of any form control that has this attribute and builds it to a form control element. Again, because we imported FormsModule from @angular/forms, we don’t need to do any special coding for this. Now let’s add ngModel property and name attribute to our two textboxes in the form. this will let #detailsForm to build two input controls where it can access to their value, among other things, in real-time. Then let’s show form’s value to see what happens if we enter data for first name and last name. if you notice, the initial value for input is empty, that’s because value attribute is empty so when form is rendered for the first time, it is produces no value inside the input. If for any reason, you need to load the form with initial value, just add that initial value to the attribute.

<input class="details-form__form-field__input" matInput placeholder="please enter first name" value="" ngModel name="firstName">

It’s great that you can make a form and access its control’s data but in real-life example, more often than not, you get data coming from API in a specific format and your form’s data should comply with that, because form’s data is eventually passed to API to be saved on a database. So we need to create a data model that contains necessary data for a specific object of interest. In our case, say we need to collect 1. first name, 2. last name, 3. gender, 4.ageaddress and consent information from the users so we need to create a person object with above attributes. Okay, lets take a look to see how we can create that data model. Inside the app folder create an empty folder and call it data-model. Inside the new folder, create a new file and name it person.model.ts or alternatively use below command to generate that via Angular CLI

ng generate class data-model/person — type=model

now inside the new file we create our Person class.

export class Person {firstName: string;lastName: string;gender: string;age: number;Address: string;consented: boolean;}

First name, last name, gender and address all could be a string value. For example first name=”Ramin”. Age is a number and consented is a boolean variable that only takes true, means yes the user checked the consent checkbox or false which means user did not provide consent.

GitHub code commit

now we need to go back to details-form component and create a person variable which is an instance of Person class.

GitHub code commit

now lets go ahead and populate the person variable with some initial values:

ngOnInit() {this.person.firstName = 'Ramin';this.person.lastName = 'Ahmadi';this.person.age = 30;this.person.gender = 'Male';this.person.Address = 'Melbourne';this.person.consented = false;}

GitHub code commit

now we need to add more controls to let user populate it with their information. From our initial form, we have input for first name and last name. First, we need to add a dropdown for age. I’m gonna use material select for dropdown and then create a an array of number and use *ngFor in the template to populate the select options.

<mat-form-field><mat-label>Age</mat-label><mat-select name="age" ngModel><mat-option *ngFor="let age of ages" [value]="age" >{{age}}</mat-option></mat-select></mat-form-field>

GitHub code commit

next, we need radio buttons for gender. The values could be “Male”, “Female”, “Neutral”, and “Prefer not to say”. While collecting data, it’s important not to lock users down with mandatory options unless it’s absolutely necessary. For example, users might not be comfortable to fit in either male or female category, so we need to add a third option to be inclusive and an exit option for users who are not comfortable disclosing any gender information. Okay, for radio buttons I’m going to use material’s radio button.

<mat-radio-group  aria-label="Select gender" ngModel name="genders" class="details-form__form-field__gender"><mat-radio-button value="Male">Male</mat-radio-button><mat-radio-button value="Female">Female</mat-radio-button><mat-radio-button value="Neutral">Neutral</mat-radio-button><mat-radio-button value="NotProvided">Prefer not to say</mat-radio-button></mat-radio-group>

GitHub code commit

Next we need a textarea for address because an address could be more than a line.

<mat-form-field class="details-form__form-field"><mat-label class="details-form__form-field__label">Address</mat-label><textarea  class="details-form__form-field__input" matInput placeholder="please enter address" value="" ngModel name="address"></textarea></mat-form-field>

GitHub code commit

And Finally a checkbox to make sure users give us their consent to store the information. The consent is a vital part of the form, specially if you plan to collect personal information of users.

GitHub code commit

Okay, we got that out the way, now lets bind our controls to the person variable. To do that we need to use banana in a box syntax or [(ngModel)]. This will bind data between the model and the form control. I’m gonna simple replace ngModel with [(ngModel)] and set the value to appropriate person property. For example, in the case of first name, I’ll use [(ngModel)]=”person.firstName” to make sure value of person.firstname as populated in initiation of the component (ngOnInit) shows inside the first name input.

<input class="details-form__form-field__input" matInput placeholder="please enter first name" value="" [(ngModel)]="person.firstName" name="firstName">

I’ll do the same for other controls to fully bind person to control values. Now reload the page and see if controls are being pre-populated with person object’s initial values.

GitHub code commit


Okay so now that two-way data binding is applied to our form, any change of value in the form should reflect in person object. Lets create a click method for save details button and after user click, lets show the collected data in an alert.

<button class="details-form__submit" mat-flat-button color="accent" (click)="onDetailsFormSubmit()">Save details</button>

And in the typescript file add below method that converts person object to a string so we can read it easily

onDetailsFormSubmit(){alert(JSON.stringify(this.person))}

GitHub code commit

As you can see entered data appears which means person object is ready to be passed to API to be saved. I’ll teach you how to create services to truly submit collected data from the form.

This tutorial is part of a series of tutorials on Angular form. if this is the first time you are seeing my tutorial, please have a look at my first tutorial on creating basic forms in Angular and then form styling in Angular. The project code is here in my personal GitHub page https://github.com/ramin-ahmadi/angular-forms and you can see a full demo on StackBlitz https://stackblitz.com/github/ramin-ahmadi/angular-forms

Feel free to reach out to me if you have any questions.

Ramin Ahmadi
I am a full-stack front end developer with over 5 years experience in web design and development. I have worked with a wide variety of environments and languages including Angular, TypeScript, NodeJS, Restful API, Microservices, Atomic design, JQuery, Material design, Progressive Web Apps, DevOps, and many Azure tools. I make it a goal to automate myself out of routine tasks in my daily work. My motto is, ‘write human readable code, lean and clean’.

Comments 0

Your email address will not be published. Required fields are marked *

Angular forms with GitHub example — tutorial 3: form data binding

log in

Captcha!

reset password

Back to
log in
Font Resize
Choose A Format
Trivia quiz
Series of questions with right and wrong answers that intends to check knowledge
Poll
Voting to make decisions or determine opinions
List
The Classic Internet Listicles
Image
Photo or GIF
Gif
GIF format