How to automatically display the new record to a list when a new record is added in Angular?

Solution for How to automatically display the new record to a list when a new record is added in Angular?
is Given Below:

I’m currently doing an Angular app with CRUD operations and Springboot API as a back end. The problem is when I add a new user, it successfully added but it does not automatically display on the List. It needs to reload the page to show the updated list.

Here’s my add-user.component.ts:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { User } from '../user';

import { UserService } from '../user.service';

@Component({
  selector: 'app-add-user',
  templateUrl: './add-user.component.html',
  styleUrls: ['./add-user.component.css']
})
export class AddUserComponent implements OnInit {

  user: User = new User();
  submitted = false;

  constructor(
    private userService: UserService,
    private router: Router,
  ) { }

  ngOnInit(): void {
  }

  save() {
    this.userService
    .addUser(this.user).subscribe(data => {
      console.log(data)
      this.user = new User();
      this.goToList();
    },
      error => console.log(error));
  }

  onSubmit() {
    this.submitted = true;
    this.save();
    this.userService.getUserList();
  }

  goToList() {
    this.router.navigate(['']);
  }
}

here’s my user-list.component.ts:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { User } from '../user';
import { UserDetailsComponent } from '../user-details/user-details.component';
import { UserService } from '../user.service';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit {
  users: Observable<User[]>;
  toUserDetails: UserDetailsComponent;
  refreshUsers = new BehaviorSubject<boolean>(true);

  constructor(
    private userService: UserService,
    private router: Router
  ) { }

  ngOnInit(): void {
    this.reloadData();
  }

  reloadData() {
    this.users = this.refreshUsers.pipe(switchMap(_ => this.userService.getUserList()));
    this.refreshUsers.next(true);
  }


  deleteUser(id: number) {
    this.userService.deleteUser(id)
      .subscribe(data => {
        console.log(data);
        this.reloadData();
      }, error => console.log(error));
  }

  userDetails(id: number) {
    this.router.navigate(['details', id]);
  }

  updateUser(id: number) {
    this.router.navigate(['update', id]);
  }
}

and here’s my user.service.ts

import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { User } from './user';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  user: User[];
  users: BehaviorSubject<User[]> = new BehaviorSubject([]);

  private BASE_URL = environment.apiBaseUrl;

  constructor(
    private http: HttpClient
  ) { }

  public getUser(id:number): Observable<User> {
    return this.http.get<User>(`${this.BASE_URL}/users/${id}`);
  }

  public addUser(user: User): Observable<User> {
    return this.http.post<User>(`${this.BASE_URL}/add`, user);
  }

  public updateUser(id: number, value: any): Observable<User> {
    return this.http.put<User>(`${this.BASE_URL}/update/${id}`, value);
  }

  public deleteUser(id: number): Observable<any> {
    return this.http.delete(`${this.BASE_URL}/delete/${id}`, {responseType: 'text'});
  }

  public getUserList(): Observable<User[]> {
    return this.http.get<User[]>(`${this.BASE_URL}/users`);
  }

}

Can anyone help me with this? Thank you.

Why not make use of the users property in your user.service.ts class definition. Instead of subscribing to the API calls you can use the users BehaviorSubject and simply update it at the end of each call and subscribe to it.

So you would have something like this:

user-list.component.ts

//...
reloadData() {
  this.users = this.refreshUsers
    // so instead of rerunning the get user list function you can just get the list
    .pipe(switchMap( _=> this.userService.users));
  this.refreshUsers.next(true);
}
//...

Now you just need to make sure that user.service.ts updates the list
with each API response.

user.service.ts

//...
export class UserService {
  user: User[];
  users: BehaviorSubject<User[]> = new BehaviorSubject([]);

  private BASE_URL = environment.apiBaseUrl;

  constructor(
    private http: HttpClient
  ) { }

  public getUser(id:number): Observable<User> {
    return this.http.get<User>(`${this.BASE_URL}/users/${id}`)
      .pipe(map((user) => {
        this.user.push(user);
        this.users.next(this.user);

        return user;
      }));
  }

  public addUser(user: User): Observable<User> {
    return this.http.post<User>(`${this.BASE_URL}/add`, user)
      .pipe(map((user) => {
        this.user.push(user);
        this.users.next(this.user);

        return user;
      }));
  }


  // With this function you would find the user and update them but this might
  // be inefficient, so what I would suggest is to use a Record<string, User> type
  // instead of User[] to keep your users then it makes the work easier.
  public updateUser(id: number, value: any): Observable<User> {
    return this.http.put<User>(`${this.BASE_URL}/update/${id}`, value);
  }

  // The case of deleteUser is the same here as well
  public deleteUser(id: number): Observable<any> {
    return this.http.delete(`${this.BASE_URL}/delete/${id}`, {responseType: 'text'});
  }

  public getUserList(): Observable<User[]> {
    return this.http.get<User[]>(`${this.BASE_URL}/users`)
      .pipe(map((users) => {
        this.user = users;
        this.users.next(this.user);

        return users;
      }));
  }

}

With this you will not be making too many unecessary requests since you have
created a small data cache for your users.

For cases like this I typically use ngrx. I would definitely
say check this out, it will provide much better solutions going forward with
this.