angularangular2-router

Angular 2 refreshing the view without route.navigate


I've built a CRUD app which communicates with a REST api but haven't found a way to refresh the view after one item is deleted. I've used router.navigate in the past to change views after other methods such as the create method and this works fine.

The problem is that the event which calls the delete method is inside the same listing of the items (every *ngFor item has its own delete event). So if I delete an item and then I use router.navigate to go to the current view it does nothing because you are already there, thus not seeing updated version of the view without the deleted item even if it has worked.

Is there any other way to refresh a view without using route.navigate?

Edit:

I've tried to implement ChangeDetectorRef, still not working though...

Here's the component:

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { ApiNoticiasService } from './api-noticias.service';
import { ROUTER_DIRECTIVES } from '@angular/router';

@Component({
  moduleId: module.id,
  selector: 'app-noticias',
  templateUrl: 'noticias.component.html',
  styleUrls: ['noticias.component.css'],
  directives: [ROUTER_DIRECTIVES],
  providers: [ApiNoticiasService]
})
export class NoticiasComponent implements OnInit {
  noticias: any;

  constructor(
    private cd: ChangeDetectorRef,
    private _apiNoticias: ApiNoticiasService) { }

  ngOnInit() {
    this._apiNoticias.getNoticias()
      .then( (noticias) => this.noticias = noticias)
      .catch((err) => {
        console.log(err);
      });
  }

  deleteNoticia(id){
    this._apiNoticias.deleteNoticia(id)
      .catch((err) => {
      console.log(err);
      });
    this.cd.markForCheck();
  }

}

And this is the method in the service:

deleteNoticia(id) {
    return this._http.delete('http://localhost:3000/noticias/' +id)
      .map((response: Response) => response.json())
      .toPromise()
      .catch((err: any) => {
        console.log(err); 
        return Promise.reject(err);
      });
  }

Solution

  • The topic you're looking for is Change Detection. The official docs seem to not have gotten around to saying much about it yet, but this blog post explains it fairly in depth.

    I'm guessing you're using on push change detection, because the default checks everything on every event and should catch your deletion automatically already. You could drop that and go back to default, but you'd lose any performance gains you were hoping to get from that setting.

    For keeping on push change detection, the section relevant to your problem is about 3/4 down the page. You need to inject a ChangeDetectorRef into the component that displays the item, and call markForCheck() on it when the deletion occurs.

    Edit: On seeing your code, your problem is actually that you are not, in fact, updating the data in your view. The server may have deleted the item, but the client's local copy is still there.

    You will need to either remove the local data manually by changing noticias appropriately, or re-fetch the whole batch from the server and replace the local cache with the newly fetched result, the same way you do in ngOnInit. The latter option must be done inside .then() on the deletion promise, otherwise getting the correct result will be subject to a race condition.