Build angular 18 forms with example

Build angular 18 forms with example

As we progress through the depths of Angular 18, we're delving into how to build forms - those digital fields where you input your information online. Our starting point? Crafting a basic contact form to lay the groundwork for understanding the essentials.

To build our form, we're tapping into Angular's toolbox, leveraging the FormGroup and FormBuilder components. These act as our building blocks, enabling us to create forms that react dynamically to user input, clicks, and submissions.

In addition to these foundational elements, we're acquainting ourselves with another approach in Angular form creation - the template-based approach. This method relies on special directives like ngForm, ngSubmit, and ngModel to simplify the form-building process.

By the end of our journey, we'll learn about how to work with forms in Angular 18, equipped with the necessary knowledge to gather ans submit information from our application users!

For our hands-on practice, we'll be using StackBlitz, an online IDE that streamlines Angular development. Just sign in with your GitHub credentials, select a ready-made Angular template, and you're all set to START A NEW APP powered by the latest Angular 18 version.

Angular 18 offers two distinct methods for handling forms: the template-based strategy and the model-based strategy. Each has its own advantages, so feel free to choose the one that suits your needs best!

Creating an Angular 18 Template-Based Form

Let's kick off our journey by constructing a simple Angular 18 form using the template-based approach. Let's tweak some settings to get things rolling.

Importing the Angular Forms Module

We'll start by opening the src/app/app.component.ts file and importing the FormsModule. Then, we add it to the imports array:

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, FormsModule],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent {
  title = 'angular18forms';
}

This imports the forms module from @angular/forms. The FormsModule is required when working with template-driven forms in Angular.

That's all we need to do to work with template-based forms in our standalone component.

Adding Angular Forms Directives

Next, open the src/app/app.component.html file, remove evrything and add the following code:

<h2>Angular 18 Template-Based Contact Form Example</h2>

<form #myform="ngForm" (ngSubmit)="onSubmit(myform)">
  <input type="text" name="fullName" placeholder="Your full name" ngModel />

  <input type="email" name="email" placeholder="Your email" ngModel />

  <textarea name="message" placeholder="Your message" ngModel></textarea>

  <input type="submit" value="Send" />
</form>

Here, we're creating our form entirely within the Angular template. We first add a template reference variable to the form and assign the ngForm key to it using the #myform="ngForm" syntax. This allows us to access the form via the myform reference.

Next, we bind the ngSubmit event to the onSubmit() method (which we'll add to our component next) and pass in the form object (via the local template variable).

Then, we register the child controls with the form. We simply add the ngModel directive and a name attribute to each element.

According to the docs, NgForm creates a top-level FormGroup instance and binds it to a form to track aggregate form value and validation status. This is done automatically when FormsModule is imported.

Now, let's add some styling. Open the src/styles.css and the add following CSS styles:

/* You can add global styles to this file, and also import other style files */

body {
    width: 100%;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

Next, open the src/app/app.component.css file and add:

form {
    display: flex;
    flex-direction: column;
}

form * {
    margin: 10px;
    padding: 12px;
    border-radius: 10px;
    border: 1px dashed #410d0d;
}

Submitting the Angular 18 Template Form

Next, let's add the onSubmit() method to the component. Open the src/app/app.component.ts file and add the following code:

import { Component } from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, FormsModule],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent {
  title = 'angular18forms';

  onSubmit(form: NgForm) {
    console.log('Your form data:', form.value);
  }
}

We pass in the reference to the NgForm object, representing our form, to the onSubmit() method, which we then use to access various properties like value, providing a plain JS object containing the form data. In this example, we simply print the form value in the console.

Here's a screenshot of our form UI:

Angular 18 Form Example

Creating an Angular 18 Reactive Form

After crafting our Angular 18 contact form using the template-based approach, let's explore creating the same example using the reactive (model-based) approach.

First, go to the src/app/app.component.ts file and import ReactiveFormsModule as follows:

import { ReactiveFormsModule } from '@angular/forms';

Next, add them to the imports array of the component:

import { Component } from '@angular/core';
import { FormsModule, NgForm, ReactiveFormsModule } from '@angular/forms';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, FormsModule, ReactiveFormsModule],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent {
  /* [...] */
}

Importing Angular's FormGroup and FormBuilder Classes

Next, in the same src/app/app.component.ts file, import the FormGroup and FormBuilder classes as follows:

import { FormGroup, FormBuilder } from '@angular/forms';

Creating a Form Group and Injecting Angular's FormBuilder

Now, define the contactForm object, which will hold our form object (an instance of FormGroup), and inject FormBuilder via the component constructor:

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, FormsModule, NgForm, ReactiveFormsModule } from '@angular/forms';
import { RouterOutlet } from '@angular/router';


@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, FormsModule, ReactiveFormsModule],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent {
  title = 'angular18forms';
  contactForm!: FormGroup;

  constructor(private formBuilder: FormBuilder){}
}

Building the Form with Angular's FormBuilder

Next, define a createContactForm() method where we'll build our form:

  createContactForm() {
    this.contactForm = this.formBuilder.group({
      fullName: [''],  
      email: [''],
      message: ['']
    });
  }

We call the group() method of the injected instance of FormBuilder to create a FormGroup of three controls: fullName, email, and message. Each control can take an optional array of options and validation rules.

Next, we call this method in the constructor:

constructor(private formBuilder: FormBuilder) {
   this.createContactForm();
}

Submitting the Angular 18 Reactive Form

Finally, add the following method, which will be called when our form is submitted:

  onSubmit() {
    console.log('Your form data:', this.contactForm.value);
  }

Now, we need to bind this form object to our HTML form. Open the src/app/app.component.html file and add the following code:

<h2> Angular 18 Reactive Contact Form Example </h2>

<form [formGroup]="contactForm" (ngSubmit)="onSubmit()">
  <input type="text" name="fullName" placeholder="Your full name" formControlName="fullName"> 
  <input type="email" name="email" placeholder="Your email" formControlName="email">
  <textarea name="message" placeholder="Your message" formControlName="message"></textarea>
  <input type="submit" value="Send">
</form> 

Here, we use property binding to bind the form using the formGroup property. Next, we use formControlName to sync the FormControl objects in contactForm with the HTML form controls by name. See the docs for more details. Finally, we bind the ngSubmit event of the form to the onSubmit() method.

Conclusion

In this tutorial, we've explored both the template-based and reactive (model-based) techniques for building a contact form in Angular 18. We've learned how to design a template-based form using directives like ngForm, ngSubmit, and ngModel, as well as a reactive form using the FormGroup and FormBuilder classes.


  • Date: