Step-by-Step: Building Angular Services for Backend API Data

Step 1: Initialize Agular Application:

ng new app-name

Step 2: Create Angular Services:

ng generate service services/app-service

Step 3: Update AppConfig File:

import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideHttpClient, withFetch } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideClientHydration(),
    provideHttpClient(withFetch()),
  ],
};

Step 4: Create a folder named "types" and add an interface for your fields:

import { Address } from './address';

export interface Employee {
  id?: number;
  name: string;
  email: string;
  contact: string;
  addresses?: Address[];
}import { Employee } from './employee';
export interface Address {
  id?: number;
  city: string;
  effectiveDate: string;
  endDate?: string;
  employee?: Employee;
}

Step 5: Write the service code to fetch data from the API:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Address } from '../types/address';

@Injectable({
  providedIn: 'root',
})
export class AddressService {
  private baseUrl = 'http://localhost:8088/api/addresses'; 

  constructor(private http: HttpClient) {}

  getAllAddresses(): Observable<Address[]> {
    return this.http.get<Address[]>(this.baseUrl);
  }

  getAddressById(id: number): Observable<Address> {
    return this.http.get<Address>(`${this.baseUrl}/${id}`);
  }

  createAddress(address: Address): Observable<Address> {
    return this.http.post<Address>(this.baseUrl, address);
  }

  updateAddress(id: number, address: Address): Observable<Address> {
    return this.http.put<Address>(`${this.baseUrl}/${id}`, address);
  }

  deleteAddress(id: number): Observable<void> {
    return this.http.delete<void>(`${this.baseUrl}/${id}`);
  }

  isDuplicateAddress(city: string, employeeId: number): Observable<boolean> {
    return this.http.get<boolean>(`${this.baseUrl}/duplicate`, {
      params: { city, employeeId: employeeId.toString() },
    });
  }

  getAddressByNameAndDate(
    employeeName: string,
    date: string
  ): Observable<Address[]> {
    return this.http.get<Address[]>(
      `${this.baseUrl}/employee/${employeeName}/date`,
      {
        params: { date },
      }
    );
  }
}
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Employee } from '../types/employee';
import { Address } from '../types/address';

@Injectable({
  providedIn: 'root',
})
export class EmployeeService {
  private baseUrl = 'http://localhost:8088/api/employees'; // Replace with your backend URL

  constructor(private http: HttpClient) {}

  getAllEmployees(): Observable<Employee[]> {
    return this.http.get<Employee[]>(this.baseUrl);
  }

  getEmployeeById(id: number): Observable<Employee> {
    return this.http.get<Employee>(`${this.baseUrl}/${id}`);
  }

  createEmployee(employee: Employee): Observable<Employee> {
    return this.http.post<Employee>(this.baseUrl, employee);
  }

  updateEmployee(id: number, employee: Employee): Observable<Employee> {
    return this.http.put<Employee>(`${this.baseUrl}/${id}`, employee);
  }

  deleteEmployee(id: number): Observable<void> {
    return this.http.delete<void>(`${this.baseUrl}/${id}`);
  }

  // Update employee addresses
  updateEmployeeAddresses(
    employeeId: number,
    addresses: Address[]
  ): Observable<Address[]> {
    const url = `${this.baseUrl}/${employeeId}/addresses`; // Assuming endpoint for updating addresses
    return this.http.put<Address[]>(url, addresses);
  }
}

Step 6: Create a components:

ng generate component components/emp/emp

ng generate component components/emp/emp-details

ng generate component components/emp/add-employee

ng generate component components/emp/add-address

ng generate component components/emp/edit-emp

Step 7: Create a Router in app.routes.ts

import { Routes } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
import { HrViewComponent } from './components/hr/hr-view/hr-view.component';
import { HrEditComponent } from './components/hr/hr-edit/hr-edit.component';
import { EmpComponent } from './components/emp/emp/emp.component';
import { EmpDetailsComponent } from './components/emp/emp-details/emp-details.component';
import { EditEmpComponent } from './components/emp/edit-emp/edit-emp.component';
import { AddEmployeeComponent } from './components/emp/add-employee/add-employee.component';
import { AddAddressComponent } from './components/emp/add-address/add-address.component';
import { AddAddressEmpComponent } from './components/emp/add-address-emp/add-address-emp.component';
import { AddEmployeeAddressComponent } from './components/emp/add-employee-address/add-employee-address.component';
import { GetAddressComponent } from './components/emp/get-address/get-address.component';

export const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'emp', component: EmpComponent },
  { path: 'add-emp', component: AddEmployeeComponent },
  { path: 'add-employee-address', component: AddEmployeeAddressComponent },
  { path: 'add-employee-address/:id', component: AddEmployeeAddressComponent },
  { path: 'get-employee-address', component: GetAddressComponent },
  { path: 'emp/:id', component: EmpDetailsComponent },
  { path: 'edit-emp/:id', component: EditEmpComponent },
  { path: 'add-address/:id', component: AddAddressComponent },
  { path: 'add-address-emp/:id', component: AddAddressEmpComponent },
  { path: 'view/:id', component: HrViewComponent },
  { path: 'edit/:id', component: HrEditComponent },
];

Step 8: Code each component according to your requirements.

Here, I will provide some detailed solutions to help you understand how to fetch APIs in real-time.

Components: [HTML & TS File]

EmpComponent:

import { Component } from '@angular/core';
import { EmployeeService } from '../../../services/employee.service';
import { Employee } from '../../../types/employee';
import { RouterLink } from '@angular/router';

@Component({
  selector: 'app-emp',
  standalone: true,
  imports: [RouterLink],
  templateUrl: './emp.component.html',
  styleUrl: './emp.component.css',
})
export class EmpComponent {
  emp: Employee[] = [];

  constructor(private empService: EmployeeService) {}

  ngOnInit() {
    this.getAllEmp();
  }

  getAllEmp() {
    this.empService.getAllEmployees().subscribe((data) => {
      this.emp = data;
    });
  }
}
<div class="px-10">
  <div class="px-10">
    <div class="flex flex-wrap gap-10 justify-start m-5 px-10">
      @for (item of emp; track $index) {
      <div class="bg-white rounded-lg shadow-md p-4 w-96">
        <div class="flex justify-between mb-2">
          <h2 class="text-xl font-bold">{{ item.name }}</h2>
        </div>
        <div class="text-sm mb-2 flex flex-col gap-y-2">
          <p><strong>Email:</strong> {{ item.email }}</p>
          <p><strong>Contact:</strong> {{ item.contact }}</p>
        </div>

        <div class="flex justify-start mt-5 mb-2">
          <button
            [routerLink]="'/emp/' + item.id"
            class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
          >
            View
          </button>
        </div>
      </div>
      }
    </div>

    <div class="flex gap-x-10">
      <div class="fixed bottom-5 right-5">
        <button
          [routerLink]="'/add-employee-address'"
          class="bg-indigo-600 text-white px-4 py-3 rounded-full shadow-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-opacity-50"
        >
          Add Employee
        </button>
      </div>
    </div>
  </div>
</div>

EmpDetailsComponent:

import { Component } from '@angular/core';
import { EmployeeService } from '../../../services/employee.service';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { Employee } from '../../../types/employee';
import { FormsModule } from '@angular/forms';
import { AddressService } from '../../../services/address.service';
import { AddressWithId } from '../../../types/add';
import { Location } from '@angular/common';
import { AddAddressComponent } from '../add-address/add-address.component';

@Component({
  selector: 'app-emp-details',
  standalone: true,
  imports: [RouterLink, FormsModule, AddAddressComponent],
  templateUrl: './emp-details.component.html',
  styleUrl: './emp-details.component.css',
})
export class EmpDetailsComponent {
  emp!: Employee;
  editing = false;
  addressForm = false;

  showAddBatchForm: boolean = false;

  employee: Employee = {
    id: 0,
    name: '',
    email: '',
    contact: '',
    addresses: [],
  };

  constructor(
    private empService: EmployeeService,
    private activatedRouter: ActivatedRoute,
    private router: Router,
    private route: ActivatedRoute,
    private addressService: AddressService,
    private location: Location
  ) {}

  ngOnInit() {
    this.getEmployeeById();
    const id = this.activatedRouter.snapshot.params['id'];
    this.fetchEmployeeData(id);
  }

  fetchEmployeeData(id: number): void {
    this.empService.getEmployeeById(id).subscribe((data: Employee) => {
      this.employee = data;
    });
  }

  submitForm(): void {
    console.log(this.employee);
    const id = Number(this.route.snapshot.paramMap.get('id'));
    // Update employee details
    this.empService.updateEmployee(id, this.employee).subscribe(
      () => {
        console.log('Employee details updated successfully');
        this.getEmployeeById();
      },
      (error) => {
        console.error('Error updating employee details:', error);
      }
    );
  }

  getEmployeeById() {
    let id = this.activatedRouter.snapshot.params['id'];
    this.empService.getEmployeeById(id).subscribe((data: Employee | null) => {
      if (data) {
        this.emp = data;
      } else {
        console.error('Employee data is null');
        this.router.navigateByUrl('/emp');
      }
    });
  }

  deleteEmp() {
    let id = this.activatedRouter.snapshot.params['id'];
    this.empService.deleteEmployee(id).subscribe(() => {
      console.log('Employee deleted successfully!');
      this.router.navigateByUrl('/emp');
    });
  }

  toggleEditing(): void {
    this.editing = !this.editing;
  }

  addressFormShown(): void {
    this.addressForm = !this.addressForm;
  }

  closeAddBatchForm() {
    this.addressForm = false;
  }
}
@if (emp) {
<div class="flex flex-wrap gap-4 justify-center items-center mt-14 m-5 px-10">
  @if (!editing) {
  <div class="bg-white rounded-lg shadow-md p-4 w-1/2">
    <div class="flex justify-between mb-2">
      <h2 class="text-xl font-bold">{{ emp.name }}</h2>
    </div>
    <div class="text-sm mb-2 flex flex-col gap-y-2">
      <p><strong>Email:</strong> {{ emp.email }}</p>
      <p><strong>Contact:</strong> {{ emp.contact }}</p>
    </div>

    <div
      class="address-items overflow-x-auto max-h-72 rounded-sm custom-scrollbar"
    >
      <table class="table-auto w-full">
        <thead>
          <tr class="bg-gray-200">
            <th class="px-4 py-2">City</th>
            <th class="px-4 py-2">Effective Date</th>
            <th class="px-4 py-2">End Date</th>
          </tr>
        </thead>

        <tbody>
          @for (address of emp.addresses; track $index) {
          <tr class="text-center odd:bg-white even:bg-slate-200">
            <td class="border px-4 py-2">
              <span class="w-[80%]">{{ address.city }} </span>
            </td>
            <td class="border px-4 py-2">
              <span class="w-[80%]">{{ address.effectiveDate }}</span>
            </td>
            <td class="border px-4 py-2">
              <span class="w-[80%]">{{
                address.endDate ? address.endDate : "Present"
              }}</span>
            </td>
          </tr>
          }
        </tbody>
      </table>
    </div>

    <!-- [routerLink]="'/edit-emp/' + emp.id" -->
    <div class="flex gap-2 mt-5">
      <button
        (click)="toggleEditing()"
        class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
      >
        Edit Details
      </button>
      <button
        (click)="deleteEmp()"
        class="bg-red-500 text-white px-4 py-2 rounded hover:bg-red-600"
      >
        Delete
      </button>
      <button
        [routerLink]="'/add-employee-address/' + emp.id"
        class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600"
      >
        Add Address
      </button>
    </div>
  </div>
  }

  <!-- Form view -->
  @if (editing) {
  <div class="bg-white rounded-lg shadow-md p-4 w-1/2">
    <form (ngSubmit)="submitForm()">
      <div class="flex justify-between mb-2">
        <input
          type="text"
          id="name"
          name="name"
          [(ngModel)]="employee.name"
          class="text-xl font-bold block w-full focus:outline-none"
          required
        />
      </div>

      <div class="text-sm mb-2 flex flex-col gap-y-2">
        <p class="flex items-center justify-center">
          <strong>Email:</strong>
          <input
            type="email"
            id="email"
            name="email"
            [(ngModel)]="employee.email"
            class="block w-full ml-1 focus:outline-none sm:text-sm"
            required
          />
        </p>
        <p class="flex items-center justify-center">
          <strong>Contact:</strong>
          <input
            type="text"
            id="contact"
            name="contact"
            [(ngModel)]="employee.contact"
            class="block w-full ml-1 focus:outline-none sm:text-sm"
            required
          />
        </p>
      </div>

      <div class="overflow-x-auto max-h-72">
        <table class="table-auto w-full">
          <thead>
            <tr class="bg-gray-200">
              <th class="px-4 py-2">City</th>
              <th class="px-4 py-2">Effective Date</th>
              <th class="px-4 py-2">End Date</th>
            </tr>
          </thead>
          <tbody>
            @for (address of emp.addresses; track $index) {
            <tr class="text-center odd:bg-white even:bg-slate-200">
              <td class="border px-4 py-2">
                <span class="w-[80%]">{{ address.city }} </span>
              </td>
              <td class="border px-4 py-2">
                <span class="w-[80%]">{{ address.effectiveDate }}</span>
              </td>
              <td class="border px-4 py-2">
                <span class="w-[80%]">{{
                  address.endDate ? address.endDate : "Present"
                }}</span>
              </td>
            </tr>
            }
          </tbody>
        </table>
      </div>

      <div class="flex gap-2 mt-5">
        <button
          type="submit"
          (click)="toggleEditing()"
          class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
        >
          Save Details
        </button>

        <button
          type="button"
          (click)="toggleEditing()"
          class="bg-gray-400 text-white px-4 py-2 rounded hover:bg-gray-600"
        >
          Cancel
        </button>
      </div>
    </form>
  </div>
  }
</div>
} @if (addressForm) {
<div>
  <app-add-address (formClosed)="closeAddBatchForm()"></app-add-address>
</div>
}

AddEmployeeComponent:

import { Component } from '@angular/core';
import { Employee } from '../../../types/employee';
import { EmployeeService } from '../../../services/employee.service';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';

@Component({
  selector: 'app-add-employee',
  standalone: true,
  imports: [FormsModule],
  templateUrl: './add-employee.component.html',
  styleUrl: './add-employee.component.css',
})
export class AddEmployeeComponent {
  employee: Employee = {
    name: '',
    email: '',
    contact: '',
    addresses: [],
  };

  address = {
    city: '',
    effectiveDate: new Date().toISOString(), // Setting current date
    endDate: '', // Setting end date to null
  };

  constructor(
    private employeeService: EmployeeService,
    private router: Router
  ) {}

  submitForm() {
    this.employee.addresses = [this.address]; // Add the address to the employee
    this.employeeService.createEmployee(this.employee).subscribe(
      (response) => {
        console.log('Employee created successfully!', response);
        this.router.navigateByUrl('/emp');
      },
      (error) => {
        console.error('Error creating employee:', error);
      }
    );
  }
}
<div class="max-w-md mx-auto bg-white p-8 rounded-xl mt-20 shadow-lg space-y-4">
  <h2 class="text-2xl font-bold text-gray-800 text-center">Employee</h2>
  <form class="space-y-6" (ngSubmit)="submitForm()">
    <div class="space-y-4">
      <!-- Employee Name -->
      <div>
        <label for="name" class="block text-sm font-medium text-gray-700"
          >Name</label
        >
        <input
          type="text"
          id="name"
          name="name"
          [(ngModel)]="employee.name"
          class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
          required
        />
      </div>

      <!-- Employee Email -->
      <div>
        <label for="email" class="block text-sm font-medium text-gray-700"
          >Email</label
        >
        <input
          type="email"
          id="email"
          name="email"
          [(ngModel)]="employee.email"
          class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
          required
        />
      </div>

      <!-- Employee Contact -->
      <div>
        <label for="contact" class="block text-sm font-medium text-gray-700"
          >Contact</label
        >
        <input
          type="text"
          id="contact"
          name="contact"
          [(ngModel)]="employee.contact"
          class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
          required
        />
      </div>

      <!-- Employee Contact -->
      <div>
        <label for="contact" class="block text-sm font-medium text-gray-700"
          >Address</label
        >
        <input
          type="text"
          id="city"
          name="city"
          [(ngModel)]="address.city"
          class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
          required
        />
      </div>
    </div>

    <!-- Submit Button -->
    <div class="mt-6">
      <button
        type="submit"
        class="w-full inline-flex items-center justify-center px-6 py-3 border border-transparent rounded-lg shadow-sm text-base font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition duration-300 ease-in-out transform hover:scale-105"
      >
        Submit
      </button>
    </div>
  </form>
</div>

AddAddressComponent:

import { Component, EventEmitter, Output } from '@angular/core';
import { AddressService } from '../../../services/address.service';
import { Address } from '../../../types/address';
import { ActivatedRoute, Router } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { EmployeeService } from '../../../services/employee.service';
import { AddressWithId } from '../../../types/add';

@Component({
  selector: 'app-add-address',
  standalone: true,
  imports: [FormsModule],
  templateUrl: './add-address.component.html',
  styleUrl: './add-address.component.css',
})
export class AddAddressComponent {
  @Output() formClosed = new EventEmitter<void>();

  address: AddressWithId = {
    city: '',
    effectiveDate: new Date().toISOString(),
    endDate: '',
    employeeId: 0,
  };

  constructor(
    private addressService: AddressService,
    private router: Router,
    private route: ActivatedRoute,
    private empService: EmployeeService
  ) {}

  closeForm() {
    this.formClosed.emit();
  }

  ngOnInit(): void {
    let id = this.route.snapshot.params['id'];
    this.address.employeeId = id;
  }

  onSubmit() {
    this.addressService.createAddress(this.address).subscribe(
      (response) => {
        let id = this.route.snapshot.params['id'];
        console.log('Employee created successfully!', response);
        this.router.navigateByUrl('/emp/' + id);
      },
      (error) => {
        console.error('Error creating employee:', error);
      }
    );
  }
}
 <!-- class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50" -->
<div
  class="fixed inset-0 flex items-center justify-center"
  (click)="closeForm()"
>
  <div
    class="w-[500px] mx-auto p-6 bg-white rounded-lg shadow-md"
    (click)="$event.stopPropagation()"
  >
    <button
      (click)="closeForm()"
      class="absolute top-0 right-0 mt-4 mr-4 text-gray-600 hover:text-gray-900"
    >
      &times;
    </button>
    <h2 class="text-2xl font-bold mb-4">Add Address</h2>
    <form (ngSubmit)="onSubmit()">
      <div class="mb-4">
        <label for="city" class="block text-sm font-medium text-gray-700"
          >City</label
        >
        <input
          id="city"
          name="city"
          type="text"
          [(ngModel)]="address.city"
          class="mt-1 block w-full p-3 border border-b rounded-md shadow-sm hover:focus:border-indigo-500 hover:focus:ring-indigo-500 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
        />
      </div>

      <!-- <div class="mb-4">
      <label for="effectiveDate" class="block text-sm font-medium text-gray-700"
        >Effective Date</label
      >
      <input
        id="effectiveDate"
        name="effectiveDate"
        type="date"
        [(ngModel)]="address.effectiveDate"
        class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
      />
    </div>

    <div class="mb-4">
      <label for="endDate" class="block text-sm font-medium text-gray-700"
        >End Date</label
      >
      <input
        id="endDate"
        name="endDate"
        type="date"
        [(ngModel)]="address.endDate"
        class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
      />
    </div> -->

      <!-- <div class="mb-4">
        <label for="employeeId" class="block text-sm font-medium text-gray-700">Employee ID</label>
        <input
          id="employeeId"
          type="number"
          formControlName="employeeId"
          class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
        />
        @if (addressForm.get('employeeId')?.invalid && addressForm.get('employeeId')?.touched) {
        <div *ngIf="addressForm.get('employeeId')?.invalid && addressForm.get('employeeId')?.touched" class="text-red-500 text-sm">
          Employee ID is required
        </div>
        }
      </div> -->

      <div class="flex justify-end">
        <button
          type="submit"
          class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-opacity-50"
        >
          Add Address
        </button>
      </div>
    </form>
  </div>
</div>

EditEmployeeComponent:

import { Component } from '@angular/core';
import { Employee } from '../../../types/employee';
import { EmployeeService } from '../../../services/employee.service';
import { ActivatedRoute, Router } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { AddressService } from '../../../services/address.service';

@Component({
  selector: 'app-edit-emp',
  standalone: true,
  imports: [FormsModule],
  templateUrl: './edit-emp.component.html',
  styleUrl: './edit-emp.component.css',
})
export class EditEmpComponent {
  employee: Employee = {
    id: 0,
    name: '',
    email: '',
    contact: '',
    addresses: [],
  };

  constructor(
    private empService: EmployeeService,
    private route: ActivatedRoute,
    private router: Router,
    private addressService: AddressService
  ) {}

  ngOnInit(): void {
    const id = Number(this.route.snapshot.paramMap.get('id'));
    this.fetchEmployeeData(id);
  }

  fetchEmployeeData(id: number): void {
    this.empService.getEmployeeById(id).subscribe((data: Employee) => {
      this.employee = data;
      // Ensure addresses is initialized
      if (!this.employee.addresses) {
        this.employee.addresses = [];
      }
    });
  }

  submitForm(): void {
    console.log(this.employee);
    const id = Number(this.route.snapshot.paramMap.get('id'));
    // Update employee details
    this.empService.updateEmployee(id, this.employee).subscribe(
      () => {
        console.log('Employee details updated successfully');
        this.router.navigateByUrl('/emp');
      },
      (error) => {
        console.error('Error updating employee details:', error);
      }
    );
  }
}
<div
  class="container mx-auto w-full flex flex-col items-center justify-center h-screen"
>
  <h1 class="text-2xl font-bold mb-4">Edit Employee Details</h1>
  <form (ngSubmit)="submitForm()" class="max-w-lg">
    <div class="mb-4">
      <label for="name" class="block text-sm font-medium text-gray-700"
        >Name</label
      >
      <input
        type="text"
        id="name"
        name="name"
        [(ngModel)]="employee.name"
        class="mt-1 block w-full px-3 py-2 border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
        required
      />
    </div>

    <div class="mb-4">
      <label for="email" class="block text-sm font-medium text-gray-700"
        >Email</label
      >
      <input
        type="email"
        id="email"
        name="email"
        [(ngModel)]="employee.email"
        class="mt-1 block w-full px-3 py-2 border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
        required
      />
    </div>

    <div class="mb-4">
      <label for="contact" class="block text-sm font-medium text-gray-700"
        >Contact</label
      >
      <input
        type="text"
        id="contact"
        name="contact"
        [(ngModel)]="employee.contact"
        class="mt-1 block w-full px-3 py-2 border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
        required
      />
    </div>

    <!-- Address Section -->
    <div class="mb-4">
      <h2 class="text-lg font-semibold mb-2">Addresses</h2>
      <table class="table-auto w-full">
        <thead>
          <tr class="bg-gray-200">
            <th class="px-4 py-2">City</th>
            <th class="px-4 py-2">Effective Date</th>
            <th class="px-4 py-2">End Date</th>
          </tr>
        </thead>
        <tbody>
          @for (address of employee.addresses; track address) {
          <tr class="bg-white">
            <td class="border px-4 py-2">
              <input
                type="text"
                name="city{{ address.city }}"
                [(ngModel)]="address.city"
                class="border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
              />
            </td>
            <td class="border px-4 py-2">
              <input
                type="text"
                name="effectiveDate{{ address.effectiveDate }}"
                [(ngModel)]="address.effectiveDate"
                class="border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
              />
            </td>
            <td class="border px-4 py-2">
              <input
                type="text"
                name="endDate{{ address.endDate }}"
                [(ngModel)]="address.endDate"
                class="border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
              />
            </td>
          </tr>
          }
        </tbody>
      </table>
    </div>

    <button
      type="submit"
      class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
    >
      Save Changes
    </button>
  </form>
</div>

GetAddressComponent:

import { Component } from '@angular/core';
import { Address } from '../../../types/address';
import { AddressService } from '../../../services/address.service';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-get-address',
  standalone: true,
  imports: [FormsModule, CommonModule],
  templateUrl: './get-address.component.html',
  styleUrl: './get-address.component.css',
})
export class GetAddressComponent {
  addresses: Address[] = [];
  employeeName: string = '';
  date: string = '';
  errorMessage: string = '';
  loading: boolean = false;

  constructor(private addressService: AddressService) {}

  ngOnInit(): void {}

  getAddressByNameAndDate(): void {
    const selectedDate = new Date(this.date);
    const today = new Date();

    if (!this.employeeName) {
      this.errorMessage = '*The name field cannot be empty.';
      this.addresses = [];
      return;
    }

    if (!this.date) {
      this.errorMessage = '*The date field cannot be empty.';
      this.addresses = [];
      return;
    }

    if (selectedDate > today) {
      this.errorMessage = '*The selected date cannot be in the future.';
      this.addresses = [];
      return;
    }

    if (this.employeeName && this.date) {
      this.loading = true;
      this.addressService
        .getAddressByNameAndDate(this.employeeName, this.date)
        .subscribe(
          (addresses: Address[]) => {
            this.addresses = addresses;
            this.errorMessage = '';
            this.loading = false;
          },
          (error) => {
            this.errorMessage = 'An error occurred while fetching addresses.';
            this.addresses = [];
            this.loading = false;
          }
        );
    }
  }

  submitForm() {}
}
<div class="max-w-md mx-auto bg-white p-8 rounded-xl mt-20 shadow-lg space-y-4">
  <h2 class="text-2xl font-bold text-gray-800 text-center">
    Find Your Address
  </h2>

  <div class="space-y-4">
    <!-- Employee Name -->
    <div>
      <label for="name" class="block text-sm font-medium text-gray-700"
        >Name</label
      >
      <input
        type="text"
        id="name"
        name="name"
        [(ngModel)]="employeeName"
        class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
        required
      />
    </div>
    <!-- [(ngModel)]="employee.name" -->

    <!-- Employee Contact -->
    <div>
      <label for="contact" class="block text-sm font-medium text-gray-700"
        >Pick Date</label
      >
      <input
        type="date"
        id="date"
        name="date"
        [(ngModel)]="date"
        class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
        required
      />
    </div>
    @if (errorMessage) {
    <div class="text-red-500 text-sm">{{ errorMessage }}</div>
    }
    <!-- [(ngModel)]="address.city" -->
  </div>

  <!-- Submit Button -->
  <!-- type="submit" -->
  <div class="mt-6">
    <button
      (click)="getAddressByNameAndDate()"
      class="w-full inline-flex items-center justify-center px-6 py-3 border border-transparent rounded-lg shadow-sm text-base font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition duration-300 ease-in-out transform hover:scale-105"
    >
      Get Address
    </button>
  </div>

  @if (addresses.length) {
  <div>
    <h3><strong>Address:</strong></h3>
    <ul class="flex items-center justify-between">
      @for (address of addresses; track $index) {
      <li>
        <strong> {{ address.city }} </strong>
      </li>
      <img src="/icons/map.png" alt="map image" height="50" width="50" />
      }
    </ul>
  </div>
  }@else if (loading) {
  <div class="flex justify-center mt-6">
    <div class="loader"></div>
  </div>
  }
</div>
0
Subscribe to my newsletter

Read articles from Vivekanand Mendhe directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vivekanand Mendhe
Vivekanand Mendhe

Hey..!