Two-way data binding is a fundamental concept in modern web development, enabling seamless synchronization between the user interface and data models. This tutorial demonstrates how to build a robust employee management system utilizing Angular for the frontend and .NET 9 for the backend. By leveraging two-way data binding, we ensure that any changes in the UI are instantly reflected in the backend and vice versa, creating a dynamic and interactive application.
The project integrates SQL Server for data storage, providing a real-world scenario for managing employee data efficiently. We’ll cover everything from setting up a new project in Visual Studio 2022 to implementing two-way data binding for creating and displaying employee records dynamically. This guide is ideal for developers looking to master full-stack development with Angular and .NET technologies while understanding the power of two-way data binding.
Prerequisites
Before starting this project, ensure you have the following tools and technologies installed on your machine:
- Visual Studio 2022 (with .NET and ASP.NET workload installed).
- Node.js (latest stable version).
- Angular CLI (install using
npm install -g @angular/cli
). - SQL Server (Express or Developer Edition).
- Basic knowledge of Angular, .NET, and SQL Server.
Learn more about angular step Angular project Setup Step by Step Practical Tutorial – Full Stack Tutorials Hub
What is Two Way Data Binding in Angular?
Two-way data binding is a mechanism where changes in the UI are automatically reflected in the model (data) and vice versa. It establishes a direct synchronization between the view and the underlying data model. This means:
- When the user updates a value in the UI (e.g., a form input), the corresponding model is updated automatically.
- When the model is updated programmatically, the UI reflects those changes instantly.
This makes it easier to manage dynamic, interactive interfaces as it eliminates the need for manual DOM updates and simplifies the flow of data in the application.
Project Setup
Backend (.NET 9)
- Open Visual Studio 2022.
- Create a new ASP.NET Core Web API project.
- Name the project
EmployeeManagement
and select .NET 9 as the target framework.
Frontend (Angular)
- Open a terminal.
- Create a new Angular project:
ng new employee-management
- Navigate to the project folder:
cd employee-management
- Add Bootstrap for styling:
npm install bootstrap
- Update
angular.json
to include Bootstrap:
Application Structure
1. Backend API
Employee Model
Create a new folder Models
in the project and add a file Employee.cs
:
namespace EmployeeManagement.Models
{
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public string Email { get; set; }
}
}
Employee Controller
Add a new controller named EmployeeController
:
using Microsoft.AspNetCore.Mvc;
using EmployeeManagement.Models;
using System.Collections.Generic;
namespace EmployeeManagement.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class EmployeeController : ControllerBase
{
private static List<Employee> employees = new List<Employee>();
[HttpGet]
public IActionResult GetAllEmployees()
{
return Ok(employees);
}
[HttpPost]
public IActionResult AddEmployee(Employee employee)
{
employee.Id = employees.Count + 1;
employees.Add(employee);
return Ok(employee);
}
}
}
In appsettings.json
, configure the connection string:
"ConnectionStrings": {
"DefaultConnection": "Server=your_server;Database=EmployeeDB;Trusted_Connection=True;"
}
Add Entity Framework Core to the project:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
Update Program.cs
to add the database context:
using Microsoft.EntityFrameworkCore;
using EmployeeManagement.Models;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddDbContext<EmployeeContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.MapControllers();
app.Run();
Create EmployeeContext
:
using Microsoft.EntityFrameworkCore;
namespace EmployeeManagement.Models
{
public class EmployeeContext : DbContext
{
public EmployeeContext(DbContextOptions<EmployeeContext> options) : base(options) { }
public DbSet<Employee> Employees { get; set; }
}
}
Run migrations:
dotnet ef migrations add InitialCreate
dotnet ef database update
2. Frontend (Angular)
Create Employee Component
Run the following command to generate a component
ng generate component employee
Employee Model
Create a file employee.model.ts
:
export interface Employee {
id: number;
name: string;
department: string;
email: string;
}
Employee Service
Create a service:
ng generate service employee
Update employee.service.ts
:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Employee } from './employee.model';
@Injectable({
providedIn: 'root',
})
export class EmployeeService {
private apiUrl = 'https://localhost:5001/api/Employee';
constructor(private http: HttpClient) {}
getEmployees(): Observable<Employee[]> {
return this.http.get<Employee[]>(this.apiUrl);
}
addEmployee(employee: Employee): Observable<Employee> {
return this.http.post<Employee>(this.apiUrl, employee);
}
}
How Two-Way Data Binding is Implemented in This Project
Two Way Data Binding in Angular Syntax
In Angular, two-way data binding is achieved using the [(ngModel)]
directive. The [(ngModel)]
directive binds an input field to a variable in the component, allowing data to flow in both directions:
- From the variable to the UI.
- From the UI back to the variable.
<input type="text" [(ngModel)]="employee.name" />
Here:
- Any change in the
employee.name
property will automatically update the input field. - Any user input in the field will update the
employee.name
property.
In this project, two-way data binding is used in the Employee Form to bind the form fields to the employee
model in the Angular component
Employee Component HTML
Update employee.component.html
:
<div class="container mt-5">
<h2>Employee Form</h2>
<form (ngSubmit)="addEmployee()">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" id="name" [(ngModel)]="employee.name" name="name" class="form-control" required />
</div>
<div class="mb-3">
<label for="department" class="form-label">Department</label>
<input type="text" id="department" [(ngModel)]="employee.department" name="department" class="form-control" required />
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" id="email" [(ngModel)]="employee.email" name="email" class="form-control" required />
</div>
<button type="submit" class="btn btn-primary">Add Employee</button>
</form>
<h3 class="mt-5">Employee List</h3>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Department</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let emp of employees">
<td>{{ emp.id }}</td>
<td>{{ emp.name }}</td>
<td>{{ emp.department }}</td>
<td>{{ emp.email }}</td>
</tr>
</tbody>
</table>
</div>
n this code:
- Each
[(ngModel)]
directive binds the input field (name
,department
, andemail
) to the corresponding property in theemployee
object. - Any changes made by the user in these fields are immediately reflected in the
employee
object in the component.
Employee Component TS
Update employee.component.ts
:
import { Component, OnInit } from '@angular/core';
import { Employee } from '../employee.model';
import { EmployeeService } from '../employee.service';
@Component({
selector: 'app-employee',
templateUrl: './employee.component.html',
styleUrls: ['./employee.component.css'],
})
export class EmployeeComponent implements OnInit {
employee: Employee = { id: 0, name: '', department: '', email: '' };
employees: Employee[] = [];
constructor(private employeeService: EmployeeService) {}
ngOnInit(): void {
this.loadEmployees();
}
loadEmployees(): void {
this.employeeService.getEmployees().subscribe((data) => (this.employees = data));
}
addEmployee(): void {
this.employeeService.addEmployee(this.employee).subscribe((newEmployee) => {
this.employees.push(newEmployee);
this.employee = { id: 0, name: '', department: '', email: '' };
});
}
}
Here:
- The
employee
object holds the data for the form. - When the user submits the form, the
addEmployee()
method is called, which sends theemployee
object to the backend API.
Run the Application
- Start the backend API:
dotnet run
- Start the Angular application:
ng serve
- Navigate to
http://localhost:4200
to see the application in action.
Displaying the Employee List
Two-way data binding also plays a role in reflecting updated data on the UI. After adding a new employee, the employees
array is updated, and the UI automatically refreshes to display the new list.
HTML (Employee List)
<tr *ngFor="let emp of employees">
<td>{{ emp.id }}</td>
<td>{{ emp.name }}</td>
<td>{{ emp.department }}</td>
<td>{{ emp.email }}</td>
</tr>
In this snippet:
- The
employees
array is bound to the table rows using*ngFor
. - Any updates to the
employees
array (e.g., adding a new employee) are immediately reflected in the table.
Why Two-Way Data Binding is Important
- Simplifies Data Management: Two-way binding eliminates the need to manually synchronize data between the UI and the model, reducing boilerplate code.
- Dynamic UI Updates: Changes in data are immediately visible in the UI, improving user experience.
- Cleaner Code: Reduces the risk of bugs caused by inconsistent data handling.
In this project, two-way data binding ensures seamless synchronization between the employee form inputs and the data model, making it easier to manage the state of the form and reflect changes in the employee list dynamically.
External Resources
Here are some helpful external resources.