Posting Data to Firebase
Build a complete form that posts data to Firebase — create, display, and delete items in real time.
Posting Data to Firebase
Let's build a complete feature that lets users create, view, and delete posts — all stored in Firebase's Realtime Database.
The Post Form Component
// post-form.component.ts
import { Component } from '@angular/core';
import { DataService } from '../services/data.service';
@Component({
selector: 'app-post-form',
templateUrl: './post-form.component.html',
styleUrls: ['./post-form.component.css']
})
export class PostFormComponent {
title = '';
content = '';
author = '';
isSaving = false;
successMessage = '';
constructor(private dataService: DataService) {}
onSubmit(): void {
if (!this.title || !this.content) return;
this.isSaving = true;
const post = {
title: this.title,
content: this.content,
author: this.author || 'Anonymous',
createdAt: new Date().toISOString(),
};
this.dataService.createPost(post).subscribe({
next: (response) => {
console.log('Saved with key:', response.name);
this.successMessage = 'Post created successfully!';
this.isSaving = false;
this.resetForm();
// Clear success message after 3 seconds
setTimeout(() => this.successMessage = '', 3000);
},
error: (err) => {
console.error('Error saving:', err);
this.isSaving = false;
}
});
}
resetForm(): void {
this.title = '';
this.content = '';
this.author = '';
}
}
The Form Template
<!-- post-form.component.html -->
<div class="form-container">
<h2>Create a New Post</h2>
<div *ngIf="successMessage" class="success">
{{ successMessage }}
</div>
<form (submit)="onSubmit()">
<div class="form-group">
<label for="title">Title</label>
<input
id="title"
[(ngModel)]="title"
name="title"
type="text"
placeholder="Post title"
required>
</div>
<div class="form-group">
<label for="author">Author</label>
<input
id="author"
[(ngModel)]="author"
name="author"
type="text"
placeholder="Your name (optional)">
</div>
<div class="form-group">
<label for="content">Content</label>
<textarea
id="content"
[(ngModel)]="content"
name="content"
rows="6"
placeholder="Write your post..."
required></textarea>
</div>
<button type="submit" [disabled]="isSaving || !title || !content">
{{ isSaving ? 'Saving...' : 'Publish Post' }}
</button>
</form>
</div>
The Post List Component
// post-list.component.ts
export class PostListComponent implements OnInit {
posts: any[] = [];
isLoading = true;
constructor(private dataService: DataService) {}
ngOnInit(): void {
this.loadPosts();
}
loadPosts(): void {
this.isLoading = true;
this.dataService.getPosts().subscribe({
next: (posts) => {
this.posts = posts.reverse(); // Newest first
this.isLoading = false;
},
error: () => {
this.isLoading = false;
}
});
}
deletePost(id: string): void {
if (!confirm('Are you sure?')) return;
this.dataService.deletePost(id).subscribe(() => {
this.posts = this.posts.filter(p => p.id !== id);
});
}
}
// post-list.component.html
<div class="post-list">
<h2>All Posts</h2>
<div *ngIf="isLoading" class="loading">Loading posts...</div>
<div *ngIf="!isLoading && posts.length === 0" class="empty">
No posts yet. Be the first to write one!
</div>
<div *ngFor="let post of posts" class="post-card">
<div class="post-header">
<h3>{{ post.title }}</h3>
<button (click)="deletePost(post.id)" class="delete-btn">
Delete
</button>
</div>
<p class="meta">
By {{ post.author }} · {{ post.createdAt | date:'medium' }}
</p>
<p>{{ post.content }}</p>
</div>
</div>
Putting It All Together
<!-- app.component.html -->
<app-header></app-header>
<div class="container">
<app-post-form></app-post-form>
<app-post-list></app-post-list>
</div>
<app-footer></app-footer>
The App Flow
User fills out form
│
▼
(submit) → PostFormComponent.onSubmit()
│
▼
DataService.createPost(post)
│ POST /posts.json → Firebase
▼
Firebase stores the data
│ Response: { "name": "-NxAbC123" }
▼
Success message shown, form resets
PostListComponent.loadPosts()
│
▼
DataService.getPosts()
│ GET /posts.json → Firebase
▼
Firebase returns all posts
│ Transform object → array with map()
▼
*ngFor renders each post as a card
Form Styles
/* post-form.component.css */
.form-container {
max-width: 600px;
margin: 30px auto;
padding: 30px;
background: white;
border-radius: 12px;
box-shadow: 0 2px 16px rgba(0,0,0,0.08);
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 6px;
font-weight: 600;
color: #333;
}
input, textarea {
width: 100%;
padding: 10px 14px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 14px;
transition: border-color 0.2s;
}
input:focus, textarea:focus {
outline: none;
border-color: #3498db;
}
button[type="submit"] {
width: 100%;
padding: 12px;
background: #3498db;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
}
button:hover:not(:disabled) { background: #2980b9; }
button:disabled { opacity: 0.6; cursor: not-allowed; }
.success {
background: #d4edda;
color: #155724;
padding: 12px;
border-radius: 8px;
margin-bottom: 20px;
}
Congratulations! 🎉
You've built a complete Angular application that:
- Creates, reads, and deletes data from Firebase
- Uses services for data management
- Has reactive forms with two-way binding
- Displays loading states and success messages
- Uses pipes for date formatting
Key Takeaways
- Use
[(ngModel)]for form two-way binding (requires FormsModule) - POST to Firebase returns a
{ name: "key" }response with the auto-generated ID - Transform Firebase object-of-objects to an array using
map() - Handle loading states (
isLoading) and saving states (isSaving) for UX - The Angular pattern: Components → Services → HTTP → Firebase