5

I have component called customers-list where I am displaying all my customers from the API:

customers-list.html

<div *ngFor="let customer of customers">
     <p>{{customer.name}</p>
</div>

customers-list.ts

import { Component Input} from '@angular/core';
import { ICustomer} from 'src/app/models/app.models';
import { CustomersService } from 'src/app/services/customers.service';

@Component({
  selector: 'drt-customers-list',
  templateUrl: './customers-list.component.html',
  styleUrls: ['./customers-list.component.scss'],
})
export class CustomerListComponent {
 public customers:  ICustomer[] ;

 constructor(public customersService: CustomersService,) {}

  public async ngOnInit(): Promise<void> {
    this.customers = await this.customersService.getCustomersList('');
  }

}

I have another component called add-customer, where I will add new customer like this:

public onaddCustomer(): void {
    this.someCustomer = this.addCustomerForm.value;
    this.customersService.addCustomer( this.someCustomer).subscribe(
      () => { // If POST is success
        this.successMessage();
      },
      (error) => { // If POST is failed
        this.failureMessage();
      }
    );

  }

Now POST operation happens fine, but the customer-list is not updated without refreshing the page.

How can I update the customers-list component after successful POST operation, without refreshing the whole page?

services file:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ICustomer} from 'src/app/models/app.models';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})

export class CustomersService {
 private  baseUrl : string = '....api URL....';

  public async getCustomersList(): Promise<ICustomer[]> {
    const apiUrl: string = `${this.baseUrl}/customers`;

    return this.http.get<ICustomer[]>(apiUrl).toPromise();
  }

public addCustomer(customer: ICustomer): Observable<object> {
  const apiUrl: string = `${this.baseUrl}/customers`;

  return this.http.post(apiUrl, customer);
}


}
user229044
  • 232,980
  • 40
  • 330
  • 338
Empty_Soul
  • 799
  • 2
  • 13
  • 31
  • You need to call this.customersService.getCustomersList('') after complete post request successfully. – Mukesh Gupta Mar 21 '19 at 11:02
  • I tried this approach, it didn't worked. – Empty_Soul Mar 21 '19 at 11:03
  • can you show how did you try, because you have to update this.customer by featching latest data from this.customerService.getCustomerList... – Mukesh Gupta Mar 21 '19 at 11:08
  • Are you using ngOnChanges to catch the customers changes ? – Mehdi Benmoha Mar 21 '19 at 11:22
  • Where in `customer-list component` or `add-customer component`? @MehdiBenmoha – Empty_Soul Mar 21 '19 at 11:23
  • in the `customer-list` component. I have had the same issue once: https://stackoverflow.com/questions/48264304/angular-5-ngonchanges-fires-only-once-in-child-component – Mehdi Benmoha Mar 21 '19 at 11:23
  • You have raised custom flags along the lines of "I need help" *sixteen times* and they have been declined *every time*. Flags are for issues that require moderator intervention, *not* for drawing attention to your question. Please stop misusing flags. – user229044 Mar 22 '19 at 04:25

3 Answers3

6

The main reason it is not refreshing because ngOnIniit executes only at the time of initialization. I am assuming you are not using any state management library ( data store ) so the best solution will be use a Subject in CustomerService. Here is the code, it may not compile, i just quickly wrote it in notepad for you. Also you need to make sure you add method is really adding customer and getCustomer method really getting the newly added customer. If both are working then my solution will work.

CustomerListComponent

import { Component Input} from '@angular/core';
import { ICustomer} from 'src/app/models/app.models';
import { CustomersService } from 'src/app/services/customers.service';

@Component({
  selector: 'drt-customers-list',
  templateUrl: './customers-list.component.html',
  styleUrls: ['./customers-list.component.scss'],
})
export class CustomerListComponent {
 public customers:  ICustomer[] ;

 constructor(public customersService: CustomersService,) {}

  public async ngOnInit(): Promise<void> {
    this.initCustomerAddedSubscription();
  }

/**
 * This subscription will execute every single time whenever a customer is added successfully
 *
 */ 
  public initCustomerAddedSubscription() {
    this.customersService.customerAdded.subscribe((data: boolean) => {
        if(data) {
            this.customers = await this.customersService.getCustomersList('');
        }
    });  

  }

}

CustomersService

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ICustomer} from 'src/app/models/app.models';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})

export class CustomersService {
 private  baseUrl : string = '....api URL....';
 // use this subject in onAddCustomer method
 public   customerAdded: Subject<boolean>;

 // constructor to initialize subject
 constructor() {
    this.customerAdded = new Subject<boolean>();
 }
 public async getCustomersList(): Promise<ICustomer[]> {
    const apiUrl: string = `${this.baseUrl}/customers`;

    return this.http.get<ICustomer[]>(apiUrl).toPromise();
  }

public addCustomer(customer: ICustomer): Observable<object> {
  const apiUrl: string = `${this.baseUrl}/customers`;

  return this.http.post(apiUrl, customer);
}


}

onaddCustomer Method

public onaddCustomer(): void {
    this.someCustomer = this.addCustomerForm.value;
    this.customersService.addCustomer( this.someCustomer).subscribe(
      () => { // If POST is success
        // You can pass in the newly added customer as well if you want for any reason. boolean is fine for now.
        this.customersService.customerAdded.next(true);
        this.successMessage();
      },
      (error) => { // If POST is failed
        this.failureMessage();
      }
    );

  }
ATHER
  • 3,254
  • 5
  • 40
  • 63
0

The ngOnInit only runs once. You have assigned the customers variable in the ngOnInit. So, it is updating only on refreshing. You need to assign the value to this.customers every time the request is completed.

Sachin Gupta
  • 4,981
  • 3
  • 16
  • 32
0
constructor(public customersService: CustomersService, private cd: ChangeDetectorRef) {}
    public onaddCustomer(): void {
        this.someCustomer = this.addCustomerForm.value;
        this.customersService.addCustomer( this.someCustomer).subscribe(
          () => { // If POST is success
            this.customers = await this.customersService.getCustomersList('');
            console.log(this.customers) //are you getting updating list here without refreshing.
             this.cd.markForCheck();
          },
          (error) => { // If POST is failed
            this.failureMessage();
          }
        );

      }
Mukesh Gupta
  • 1,373
  • 3
  • 17
  • 42