2

I have a strange scenario occurring where I am displaying an angular material table of customer first names and last names. There is an "Add Customer Button" that pops up a modal to add a new customer in there. When you click Submit, it adds the customer to the customer array and the table updates. However, this only happens the first time you do it. Subsequent attempts do nothing. The customer array keeps being updated but the Observable the datasource is bound to from the data service appears to become detached from it and keeps the same array(it updates only the first time). Unsure what I am doing wrong here as it is my first foray into Angular 7. Any help would be greatly appreciated, this has been driving me crazy for about an hour now.

data-service.ts

import { Injectable } from '@angular/core';
import { Observable} from 'rxjs';
import {Customers} from './ICustomer';

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

  customers: Customers[] = [
    {
    firstName: 'Matt',
    lastName: 'Osman'
    },
    {firstName: 'Josh',
    lastName: 'Allen'}
];

// get customers from the customer array
public getCustomers(): any {
  const customersObservable = new Observable(observer => {
    setTimeout(() => {
      observer.next(this.customers);
    }, 1000);
  });
  return customersObservable;
}
// add customers to the customer array
public addCustomers(data: any): any {
  this.customers.push(data);
  this.customers = [...this.customers];
}
constructor() {}
}

ICustomer.ts //customer interface

export interface Customers {
    firstName: string;
    lastName: string;
  }

customer-data-table.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import {MatTable} from '@angular/material';
import {DataServiceService} from '../data-service.service';
import {Customers} from '../ICustomer';
import {MatDialog} from '@angular/material/dialog';
import { AddCustomerModalComponent } from '../add-customer-modal/add-customer-modal.component';

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

  displayedColumns: string[] = ['firstName', 'lastName'];
  dataSource: Customers[] = [];

  firstName: string;
  lastName: string;

  // needed to update the data in the table after adding
  @ViewChild(MatTable, {static: false}) table: MatTable<any>;

  constructor(private customerService: DataServiceService, public dialog: MatDialog) { }

  numEmployees() {
    return this.dataSource.length;
  }
// this handles the dialog open/close events
  openDialog(): void {
    const dialogRef = this.dialog.open(AddCustomerModalComponent, {
      width: '75%',
      data: {firstName: this.firstName, lastName: this.lastName}
    });

    dialogRef.afterClosed().subscribe(result => {
      console.log('the dialog was closed');
      this.customerService.addCustomers(result); **<-- the customers[] continues updating but NOT the datasource observing it**
      this.table.renderRows();
    });
  }
  // subscribe to the dataService to connect to the customer list.
  ngOnInit() {
    const customersObservable = this.customerService.getCustomers();
    customersObservable.subscribe((customersData: Customers[]) => {
      this.dataSource = customersData; **<--- THIS UPDATES ONLY THE FIRST TIME THEN STOPS UPDATING WHEN NEW CUSTOMERS ARE ADDED**
    });
    }
}

add-customer-modal.ts

import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Component, Inject } from '@angular/core';
import {Customers} from '../ICustomer';

@Component({
  selector: 'app-add-customer-modal',
  templateUrl: './add-customer-modal.component.html',
  styleUrls: ['./add-customer-modal.component.css']
})
export class AddCustomerModalComponent {


  constructor( public dialogRef: MatDialogRef<AddCustomerModalComponent>,
               @Inject(MAT_DIALOG_DATA) public data: Customers) { }

  onCancel(): void {
    this.dialogRef.close();
  }
}

UPDATE:

Issue is solved by one simple change...

In the addCustomers method in data-service.services.ts I commented out the following line:

this.customers = [...this.customers];

and now it works as I need it to...I guess this makes sense since it is creating a new object each time instead of using the same object.

MattE
  • 1,044
  • 1
  • 14
  • 34
  • the other option is get in a variable the table (using ViewChild) and use table.renderRows(), see https://stackoverflow.com/questions/47581267/how-to-add-data-dynamically-to-mat-table-datasource/56948608#56948608 – Eliseo Jul 21 '19 at 16:41

0 Answers0