Dominikus Dermann
Dominikus Dermann

Reputation: 41

Angular 6: Update Table in one component after adding data to another component

I have create a single page application in Angular 6 with two components. The are communicating to a web-server through a data service. One component lists all the item, the other component allows the user to add an item to that list. Interestingly, by calling getItems after deleting one item in the list component it refreshes the list, which calling get MatTableDataSource attribute from the create component does not. Any points are hugely appreciated. Thanks.

List component:

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';
import { MatTableDataSource } from '@angular/material/table';

import { Item } from '../items.model';

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

  public items = new MatTableDataSource<Item>();
  private displayedColumns = ['name', 'status', 'actions'];

  constructor(private data: DataService) { }

  ngOnInit() {
    this.getItems();
    console.log('New list page initialized');
  }

  getItems() {
    this.data.getItems().subscribe( (items: Item[]) => {
      this.items.data = items;
      console.log(this.items);
    });
  }

  deleteItem(id) {
    this.data.deleteItem(id).subscribe( (res) => {
      console.log(res);
      this.getItems();
    });
  }
}

Create component:

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';
import { ListComponent } from '../list/list.component';
import { Item } from '../items.model';

import { MatSnackBar } from '@angular/material';

import {FormGroup, FormBuilder, Validators } from '@angular/forms';


@Component({
  selector: 'app-create',
  providers: [ListComponent],
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {

  createForm: FormGroup;

  constructor(private list: ListComponent ,private data: DataService, private fb: FormBuilder, private snackBar: MatSnackBar) {
    this.createForm = this.fb.group( {
      name: ['', Validators.required],
      status: ['']
    });
   }

  ngOnInit() {
  }

  addItem(name) {
    this.data.postItem(name).subscribe( (res) => {
      console.log(res);
      this.data.getItems().subscribe( (item: Item[])  => {
        this.list.items.data = item;
      })
      this.snackBar.open('Your item was succesfully added to the shopping list.', 'Cool!', {
        duration: 3000
      });
    });
  }
}

Data Service:

    @Injectable({
  providedIn: 'root'
})
export class DataService {

  API_URL: string = 'https://cookie-munchies.herokuapp.com/api/items';

  constructor(private http : HttpClient) { }

  getItems(){
    return this.http.get(this.API_URL);
  }

  postItem(name){
    let item = {
      name: name,
    };

    return this.http.post(this.API_URL, item);
  }

  deleteItem(id) {
    return this.http.delete(`${this.API_URL}/${id}`);
  }

  updateItem(id, item: Item) {
    // TODO: write update function
    return this.http.put(`${this.API_URL}/${id}`, item);
  }
}

Upvotes: 3

Views: 2056

Answers (1)

Rinkal Rawat
Rinkal Rawat

Reputation: 51

What I understand from your question that you need to add data from a component and display it as updated in other component list. To achieve this you can use the feature of rxjs i,e subject.

In your DataService:

//declare a subject instance

private subject =new Subject<any>();

//Value is any string message or boolean value
//this will notify that you have added or deleted the data successfully and you //want other component to listen that

sendNotification(value:any)
{
    this.subject.next({text:value});
}

//this will be subscribed by the listing component which needs to display the //added/deleted ie updated list.

getNotification(){
    return this.subject.asObservable();
}

//In the method which you are saving data either by http client or in a list. In //its success call sendNotification method.

postItem(name){
    let item = {
      name: name,
    };

    return this.http.post(this.API_URL, item).pipe(
      map((data=>{
        this.sendNotification(true);
        }
      }
    )));
  }
 deleteItem(id) {
    return this.http.delete(`${this.API_URL}/${id}`).pipe(
      map((data=>{
        this.sendNotification(true);
        }
      }
    )));;
  }

In your List Component ts Add the following code:

// create a field of type Subscription
subscription:Subscription

//then add the following code in constructor:

constructor(private data: DataService){
this.subscription=this.dataService.getNotification().subscribe(data=>{
      if(data)
      {
        this.getItems();
      }
    });
}

It will work fine and will update your list with every addition and deletion.

Always unsubscribe the subject after component disposed off to avoid unwanted memory leaks in your listing component.

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

Upvotes: 5

Related Questions