Build a contact form in Angular using Reactive Forms and HttpClient. FormsList handles the backend. No Express or NestJS server required.
TL;DR
To add a contact form to Angular, use Reactive Forms with HttpClient to POST form data to `https://formslist.com/f/your-form-id`. FormsList handles submissions. No Express or NestJS backend required.
Sign up for a free FormsList account and create a new form. Copy the endpoint URL from your dashboard.
// Your endpoint will look like this:
// https://formslist.com/f/YOUR_FORM_HASHGenerate a new component with `ng generate component contact-form`. Use ReactiveFormsModule to define a FormGroup with validators. The onSubmit method collects form values, builds a FormData object, and posts to FormsList via fetch.
// contact-form.component.ts
import { Component } from '@angular/core';
import { ReactiveFormsModule, FormGroup, FormControl, Validators } from '@angular/forms';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-contact-form',
standalone: true,
imports: [ReactiveFormsModule, CommonModule],
templateUrl: './contact-form.component.html',
})
export class ContactFormComponent {
status: 'idle' | 'sending' | 'sent' | 'error' = 'idle';
contactForm = new FormGroup({
name: new FormControl('', [Validators.required]),
email: new FormControl('', [Validators.required, Validators.email]),
message: new FormControl('', [Validators.required]),
});
async onSubmit() {
if (this.contactForm.invalid) return;
this.status = 'sending';
const formData = new FormData();
formData.append('name', this.contactForm.value.name ?? '');
formData.append('email', this.contactForm.value.email ?? '');
formData.append('message', this.contactForm.value.message ?? '');
try {
const res = await fetch('https://formslist.com/f/YOUR_FORM_HASH', {
method: 'POST',
body: formData,
});
if (res.ok) {
this.status = 'sent';
this.contactForm.reset();
} else {
this.status = 'error';
}
} catch {
this.status = 'error';
}
}
}Add the HTML template for your contact form component. Angular's reactive form directives bind the form controls to the template.
<!-- contact-form.component.html -->
<form [formGroup]="contactForm" (ngSubmit)="onSubmit()" class="space-y-4 max-w-md">
<div>
<label for="name" class="block text-sm font-medium">Name</label>
<input
id="name"
formControlName="name"
type="text"
class="mt-1 block w-full rounded border p-2"
/>
</div>
<div>
<label for="email" class="block text-sm font-medium">Email</label>
<input
id="email"
formControlName="email"
type="email"
class="mt-1 block w-full rounded border p-2"
/>
</div>
<div>
<label for="message" class="block text-sm font-medium">Message</label>
<textarea
id="message"
formControlName="message"
rows="4"
class="mt-1 block w-full rounded border p-2"
></textarea>
</div>
<button
type="submit"
[disabled]="status === 'sending' || contactForm.invalid"
class="rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-700 disabled:opacity-50"
>
{{ status === 'sending' ? 'Sending...' : 'Send Message' }}
</button>
<p *ngIf="status === 'sent'" class="text-green-600">Message sent successfully!</p>
<p *ngIf="status === 'error'" class="text-red-600">Something went wrong. Please try again.</p>
</form>Run `ng serve`, navigate to the page with your form, and submit a test message. Verify it appears in your FormsList dashboard. Enable email notifications, Slack integration, or auto-responders from the dashboard.
Either works. This guide uses the native fetch API for simplicity. If you prefer Angular's HttpClient, inject it and use this.http.post() with the FormData body instead.
Check formControl.invalid and formControl.touched in your template. Angular Reactive Forms track dirty, touched, and validity state for each control; combine with *ngIf to show inline error messages.
Yes. The form submission happens client-side via fetch, so it works the same whether your Angular app uses SSR or client-side rendering. No server-side handler is needed.
200 free submissions a month and a live endpoint in 30 seconds. No server, no credit card, just point your form at it.