0

I'm adding my data through ng-bootstrap modal but i have a problem since when i click the add button, it needs to be refresh before i can see the new added data. I already called the this.getMaterials() when i successfully added the product but it still needs to be refreshed before i can see the new added data

export class MaterialsListComponent implements OnInit {
  closeResult: string;
    materials: any;
    subscription: Subscription;

  constructor(private modalService: NgbModal, private materialsService: MaterialsService) { }

  ngOnInit() {
    this.getAllMaterials();
  }

  getAllMaterials() {
    this.subscription = this.materialsService.getAll()
        .subscribe(
          (data:any) => {
            this.materials = data;
            console.log(data);
          },
          error => {
           console.log(error);
          });
  }

  onCreateMaterial(form: NgForm){
    const name = form.value.name;
    const description = form.value.description;
    this.materialsService.addMaterial(name, description)
      .subscribe(
          data => {
            this.getAllMaterials();
            console.log(data);
          },
          error => {
             console.log(error);
          });
  }

  open(content) {
      this.modalService.open(content).result.then((result) => {
        this.closeResult = `Closed with: ${result}`;
      }, (reason) => {
        this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
      });
    }

    private getDismissReason(reason: any): string {
      if (reason === ModalDismissReasons.ESC) {
        return 'by pressing ESC';
      } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
        return 'by clicking on a backdrop';
      } else {
        return  `with: ${reason}`;
      }
    }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

}

service

export class MaterialsService {
  url = AppSettings;
  materials: any;

  constructor(private httpClient: HttpClient) {}

 getAll() {
    if(!this.materials) {
        this.materials = this.httpClient.get<any>(this.url)
                            .map((response => response))   
                            .publishReplay(1)
                            .refCount();

    }
    return this.materials;
  }

  addMaterial(name: string, description: string) {
    return this.httpClient
    .post(
       this.url, 
       JSON.stringify({ name, description})
    )
    .map((response: any) => {
         return response;
        });
  }
  • You should use RxJs Subject for refresh data real-time. http://reactivex.io/documentation/subject.html – Ha Hoang Oct 09 '17 at 03:05
  • @HaHoang. It would be great if you can help me with my code. Thank you –  Oct 09 '17 at 03:25

2 Answers2

1

I would sa you need to call getAllMaterial() when the modal is closed (assuming that the user has added some material through the opened modal)

open(content) {
      this.modalService.open(content).result.then((result) => {
        this.closeResult = `Closed with: ${result}`;
        this.getAllMaterials();
      }, (reason) => {
        this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
      });
}
Mehdi
  • 2,263
  • 1
  • 18
  • 26
0

I don't know how your service is doing.

So in your MaterialsService, you should declaring a BehaviorSubject as below:

import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs/BehaviorSubject'

@Injectable()
export class MaterialsService {
  materials: Observable<any[]> // any : your data type
  // store data
  private store: {
    materials: any[]
  };
  private _source: BehaviorSubject<any[]>;

  constructor(private http: Http) {
     this._source = <BehaviorSubject<any[]>>new BehaviorSubject([]);
     this.store = { materials: [] };

     this.materials = this._source.asObservable();
  }

  getAll() {
     this.http.get(`${this.baseUrl}/materials`).map(response => response.json())
       .subscribe(materials => {
         this.store.materials= materials;

         this._source.next(Object.assign({}, this.store).materials);
     }, error => console.log('Could not load materials.'));
  }

  addMaterial(name, description) {
     this.http.post(`${this.baseUrl}/materials`, JSON.stringify({name, description}))
      .map(response => response.json()).subscribe(data => {
         this.store.materials.push(data);

         this._source.next(Object.assign({}, this.store).materials);
     }, error => console.log('Could not add material.'));
  }
  ...
}

In your MaterialsListComponent, you subscribe to an Observable:

export class MaterialsListComponent implements OnInit {
  materials: Observable<any[]>;

  constructor(private modalService: NgbModal,
              private materialsService: MaterialsService) { }

  ngOnInit() {
    this.materials = this.materialsService.materials;
  }
}

Each time there is a new value emitted from our Observable Angular updates the view.

<!-- Async pipe is used to bind an observable directly in your template -->
<div *ngFor="let item of materials | async">
  {{ item.name }}
</div>

Hope this help!

Ha Hoang
  • 1,644
  • 12
  • 14