FS
Programmers Picnic
Angular Lessons by Champak Roy
Angular Forms Lesson

Form Submission in Angular: Level 0 to Infinity

Learn how Angular forms collect user input, validate it, submit it, show loading and error states, send it to an API, reset it, upload files, handle dynamic fields, and become production-ready.

Start Lesson
Speak tag: speak0

1. Introduction to Angular Form Submission

Form submission means collecting user input from a form and then using that data. In real apps, submitted form data may log in a user, add a student, update a profile, or send a contact message.

Simple meaning: A user fills fields, clicks submit, Angular validates the data, and your component decides what to do next.
User fills form
↓
User clicks Submit
↓
Angular receives ngSubmit
↓
Component validates data
↓
Component sends data to service/API
↓
Show success or error

Checkpoint: Verify before continuing

Complete all checks to continue.

Speak tag: speak1

2. Level 0 Meaning

An Angular form is not just HTML. Angular can track values, validity, touched state, dirty state, errors, and submission.

HTML FormShows input fields and submit button.
Angular Form ModelTracks values, errors, and validity.
Submit MethodRuns when the user submits the form.
<form (ngSubmit)="submitForm()">
  <input name="studentName">
  <button type="submit">Submit</button>
</form>

Checkpoint

Complete all checks to continue.

Speak tag: speak2

3. Why Form Submission Matters

Login pages, registration pages, admin panels, dashboards, feedback pages, search filters, and payment flows all depend on forms.

Use Case Form Fields Submit Result
Login Email, password Authenticate user
Student registration Name, email, course Create student record
Contact form Name, email, message Send message to owner
Profile update Name, phone, address Update existing user

Checkpoint

Complete all checks to continue.

Speak tag: speak3

4. Two Angular Form Approaches

Angular provides two main approaches to forms: template-driven forms and reactive forms. Both track values and validation, but they organize the code differently.

Approach Import Best For Mental Model
Template-driven form FormsModule Simple forms HTML-first
Reactive form ReactiveFormsModule Complex forms, validation, dynamic fields, testing TypeScript-first
Beginner rule: use template-driven forms for quick simple forms. Use reactive forms for serious Angular projects.

Checkpoint

Complete all checks to continue.

Speak tag: speak4

5. Setup a Practice Component

Command

ng generate component pages/form-submission-demo

Add Route

import { Routes } from '@angular/router';
import { FormSubmissionDemo } from './pages/form-submission-demo/form-submission-demo';

export const routes: Routes = [
  { path: 'form-submission', component: FormSubmissionDemo }
];

Run

ng serve

Open:

http://localhost:4200/form-submission

Checkpoint

Complete all checks to continue.

Speak tag: speak5

6. Template-driven Form Submission

A template-driven form is easy to start. The form structure is mostly in HTML, and Angular creates the form model through directives like ngModel.

form-submission-demo.ts

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

@Component({
  selector: 'app-form-submission-demo',
  imports: [FormsModule],
  templateUrl: './form-submission-demo.html',
  styleUrl: './form-submission-demo.css'
})
export class FormSubmissionDemo {
  student = { name: '', email: '', course: 'Angular' };
  submittedData: unknown = null;

  submitTemplateForm(): void {
    this.submittedData = { ...this.student };
    console.log('Template-driven form submitted:', this.submittedData);
  }
}

form-submission-demo.html

<h2>Template-driven Form</h2>

<form #studentForm="ngForm" (ngSubmit)="submitTemplateForm()">
  <label>Name
    <input name="name" [(ngModel)]="student.name" required minlength="3">
  </label>

  <label>Email
    <input name="email" type="email" [(ngModel)]="student.email" required>
  </label>

  <label>Course
    <select name="course" [(ngModel)]="student.course">
      <option value="Angular">Angular</option>
      <option value="TypeScript">TypeScript</option>
      <option value="JavaScript">JavaScript</option>
    </select>
  </label>

  <button type="submit" [disabled]="studentForm.invalid">Submit</button>
</form>

@if (submittedData) {
  <pre>{{ submittedData | json }}</pre>
}

Checkpoint

Complete all checks to continue.

Speak tag: speak6

7. Reactive Form Submission

Reactive forms define the form model in TypeScript. This makes validation, testing, dynamic controls, and complex submit logic easier to manage.

form-submission-demo.ts

import { Component } from '@angular/core';
import { ReactiveFormsModule, FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-form-submission-demo',
  imports: [ReactiveFormsModule],
  templateUrl: './form-submission-demo.html',
  styleUrl: './form-submission-demo.css'
})
export class FormSubmissionDemo {
  registrationForm = new FormGroup({
    name: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.minLength(3)] }),
    email: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.email] }),
    course: new FormControl('Angular', { nonNullable: true, validators: [Validators.required] })
  });

  submittedData: unknown = null;

  submitReactiveForm(): void {
    if (this.registrationForm.invalid) {
      this.registrationForm.markAllAsTouched();
      return;
    }

    this.submittedData = this.registrationForm.getRawValue();
    console.log('Reactive form submitted:', this.submittedData);
  }
}

form-submission-demo.html

<h2>Reactive Form</h2>

<form [formGroup]="registrationForm" (ngSubmit)="submitReactiveForm()">
  <label>Name <input formControlName="name"></label>
  @if (registrationForm.controls.name.invalid && registrationForm.controls.name.touched) {
    <p class="error">Name is required and must have at least 3 characters.</p>
  }

  <label>Email <input type="email" formControlName="email"></label>
  @if (registrationForm.controls.email.invalid && registrationForm.controls.email.touched) {
    <p class="error">Enter a valid email.</p>
  }

  <label>Course
    <select formControlName="course">
      <option value="Angular">Angular</option>
      <option value="TypeScript">TypeScript</option>
    </select>
  </label>

  <button type="submit" [disabled]="registrationForm.invalid">Submit Reactive Form</button>
</form>

Checkpoint

Complete all checks to continue.

Speak tag: speak7

8. Validation Before Submit

Validation checks whether the entered data is acceptable. Good forms should not submit invalid data.

Validator Meaning Example
Validators.required Field cannot be empty Name, email, password
Validators.email Must look like an email student@example.com
Validators.minLength(3) Minimum number of characters Name should not be too short
Validators.pattern(...) Must match a pattern Phone, username
submitReactiveForm(): void {
  if (this.registrationForm.invalid) {
    this.registrationForm.markAllAsTouched();
    return;
  }

  const formValue = this.registrationForm.getRawValue();
  console.log(formValue);
}

Checkpoint

Complete all checks to continue.

Speak tag: speak8

9. Important Form States

Angular tracks useful states for each control and form. These states help decide when to show errors.

State Meaning Use
valid All validations passed Enable submit
invalid At least one validation failed Disable submit or show errors
touched User focused and left the field Show error after interaction
dirty User changed the value Warn about unsaved changes
pending Async validation is running Show checking status

Checkpoint

Complete all checks to continue.

Speak tag: speak9

10. Submit Form Data to an API

In a real app, the component should call a service, and the service should handle the HTTP request.

Provide HTTP Client

import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [provideHttpClient()]
};

student.service.ts

import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

export interface StudentRegistration {
  name: string;
  email: string;
  course: string;
}

@Injectable({ providedIn: 'root' })
export class StudentService {
  private http = inject(HttpClient);
  private apiUrl = 'https://example.com/api/students';

  registerStudent(data: StudentRegistration): Observable<StudentRegistration> {
    return this.http.post<StudentRegistration>(this.apiUrl, data);
  }
}

Checkpoint

Complete all checks to continue.

Speak tag: speak10

11. Loading, Success, and Error States

A production form should show what is happening. The user should know when the form is submitting, when it succeeded, and when it failed.

isSubmitting = false;
successMessage = '';
errorMessage = '';

submitReactiveForm(): void {
  if (this.registrationForm.invalid) {
    this.registrationForm.markAllAsTouched();
    return;
  }

  this.isSubmitting = true;
  this.successMessage = '';
  this.errorMessage = '';

  const data = this.registrationForm.getRawValue();

  this.studentService.registerStudent(data).subscribe({
    next: () => {
      this.successMessage = 'Registration saved successfully.';
      this.registrationForm.reset({ name: '', email: '', course: 'Angular' });
    },
    error: () => {
      this.errorMessage = 'Something went wrong. Please try again.';
    },
    complete: () => {
      this.isSubmitting = false;
    }
  });
}

Checkpoint

Complete all checks to continue.

Speak tag: speak11

12. Reset Form after Submit

After successful submission, you may want to clear the form or restore default values.

Reactive Form Reset

this.registrationForm.reset({
  name: '',
  email: '',
  course: 'Angular'
});

Template-driven Form Reset

submitTemplateForm(form: NgForm): void {
  if (form.invalid) {
    return;
  }

  console.log(form.value);
  form.resetForm({ course: 'Angular' });
}

Checkpoint

Complete all checks to continue.

Speak tag: speak12

13. File Upload Form Submission

File upload usually uses FormData instead of a normal JSON object.

HTML

<form (ngSubmit)="submitFileForm()">
  <input type="file" (change)="onFileSelected($event)">
  <button type="submit" [disabled]="!selectedFile">Upload</button>
</form>

TypeScript

selectedFile: File | null = null;

onFileSelected(event: Event): void {
  const input = event.target as HTMLInputElement;

  if (input.files && input.files.length > 0) {
    this.selectedFile = input.files[0];
  }
}

submitFileForm(): void {
  if (!this.selectedFile) {
    return;
  }

  const formData = new FormData();
  formData.append('file', this.selectedFile);
  console.log('Ready to upload:', formData);
}

Checkpoint

Complete all checks to continue.

Speak tag: speak13

14. Dynamic Form Submission with FormArray

Dynamic forms allow users to add or remove fields. In reactive forms, FormArray is used for repeated controls.

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

skillsForm = new FormGroup({
  studentName: new FormControl('', { nonNullable: true }),
  skills: new FormArray([
    new FormControl('Angular', { nonNullable: true })
  ])
});

get skills(): FormArray<FormControl<string>> {
  return this.skillsForm.controls.skills;
}

addSkill(): void {
  this.skills.push(new FormControl('', { nonNullable: true }));
}

removeSkill(index: number): void {
  this.skills.removeAt(index);
}

Checkpoint

Complete all checks to continue.

Speak tag: speak14

15. Security and Reliability Rules

Frontend validation improves user experience, but it is not enough for security. A backend must validate submitted data again.

Rule Reason
Validate on frontend Helps users correct mistakes quickly.
Validate on backend Prevents malicious or invalid data from being accepted.
Do not store secrets in Angular Frontend code is visible after deployment.
Disable duplicate submit Prevents accidental multiple requests.

Checkpoint

Complete all checks to continue.

Speak tag: speak15

16. Deployment Checks for Your Angular Site

Your Angular site URL is:

https://angular.learnwithchampak.live/

For this custom domain root, use base href:

/

Build and Deploy

npm run build:github
npm run deploy:github

Recommended package.json Scripts

"build:github": "ng build --configuration production --base-href /",
"deploy:github": "ng deploy --base-href=/"

Checkpoint

Complete all checks to continue.

Speak tag: speak16

17. Expert Form Submission Patterns

Expert Angular form submission focuses on typed forms, services, clean state, reusable validators, error mapping, and maintainable architecture.

Typed FormsKeep form values predictable with specific types.
Service LayerKeep HTTP code outside the component.
Error MappingConvert backend errors into user-friendly messages.
interface RegistrationPayload {
  name: string;
  email: string;
  course: string;
}

function mapFormToPayload(formValue: RegistrationPayload): RegistrationPayload {
  return {
    name: formValue.name.trim(),
    email: formValue.email.trim().toLowerCase(),
    course: formValue.course
  };
}

Checkpoint

Complete all checks to continue.

Speak tag: speak17

18. Common Mistakes

Mistake Problem Fix
Forgetting FormsModule ngModel does not work. Import FormsModule.
Forgetting ReactiveFormsModule formGroup and formControlName do not work. Import ReactiveFormsModule.
Using ngModel without name Template-driven form control may not register. Add a unique name attribute.
Submitting invalid forms Bad data enters the app. Check form.invalid before submit.
No loading state User may click submit repeatedly. Use isSubmitting.

Checkpoint

Complete all checks to continue.

Speak tag: speak18

19. Student Assignment

Create a complete form submission page called Student Registration.

Requirements

1. Create a route: /form-submission
2. Create a reactive form.
3. Fields: name, email, course, phone, message.
4. Add validators.
5. Disable submit when invalid.
6. Show error messages after touch or submit attempt.
7. Show loading text during submit.
8. Show success message after submit.
9. Reset form after successful submit.
10. Keep API call inside a service.

Final Test

ng serve

Open:

http://localhost:4200/form-submission

Final Checkpoint

Complete all checks to finish.

Final learning: Angular form submission includes form model, validation, state, service call, error handling, reset, and deployment testing.
Speak tag: speak19

Final Summary

Question Answer
What listens to form submit? (ngSubmit)
What does template-driven form need? FormsModule
What does reactive form need? ReactiveFormsModule
What blocks invalid submit? Check form.invalid and return.
What prevents double submit? isSubmitting and disabled submit button.
Where should API code go? Inside a service.
How should your custom domain deploy? ng deploy --base-href=/