1

I am trying to push edited form data from edit-customers-dialog.ts to an array of objects in my datasource. The form.data.value comes back correctly, but it is not being inserted into the array properly.

I am having trouble finding the correct syntax on pushing to an interface data type. Please help as I'm new to angular. Thanks!

customers.html

      <mat-card-title>         
            <button id="invite" mat-raised-button color="primary" type="button" (click)="addCustomer()">
                  Add Customer
                </button>
          </mat-card-title>
    <mat-card-content>

        <table mat-table [dataSource]="dataSource.data" class="mat-elevation-z8">

            <!-- Name Column -->
            <ng-container matColumnDef="name">
                <th mat-header-cell *matHeaderCellDef> Name </th>
                <td mat-cell *matCellDef="let row"> {{row.name}} </td>
            </ng-container>

            <!-- Address Column -->
            <ng-container matColumnDef="address">
                <th mat-header-cell *matHeaderCellDef> Address </th>
                <td mat-cell *matCellDef="let row"> {{row.address}}</td>
            </ng-container>

            <!-- Actions Column -->
            <ng-container matColumnDef="actions">
                <th mat-header-cell *matHeaderCellDef> Actions </th>
                <td mat-cell *matCellDef="let row">
                    <ng-container>
                        <button id="edit" mat-icon-button color="primary" title="Update Customer" (click)="editCustomer(row)" >
                            <mat-icon>edit</mat-icon>
                        </button>
                        <button id="delete" mat-icon-button color="warn" title="Delete Customer" (click)="deleteCustomer(row)">
                            <mat-icon>delete</mat-icon>
                        </button>

                    </ng-container>
                </td>
            </ng-container>

            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
            <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

        </table>
        <mat-paginator 
        showFirstLastButtons
        [length] = "0"
        [pageSizeOptions]="[25, 50, 75]" 
        >
    </mat-paginator>
    </mat-card-content>
</mat-card>

customers.component.ts

import {MatTableDataSource} from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog/';      
import { AddCustomerDialogComponent } from '../customers/add-customer-dialog/add-customer-dialog.component';
import { EditCustomerDialogComponent } from '../customers/edit-customer-dialog/edit-customer-dialog.component';
import {CustomerDataSource, CustomerListItem } from './customer.datasource';

@Component({
  selector: 'app-customers',
  templateUrl: './customers.component.html',
  styleUrls: ['./customers.component.css']
})
export class CustomersComponent implements OnInit { 
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild (MatSort) sort: MatSort;

  dataSource: CustomerDataSource;
  customer: CustomerListItem [];
  displayedColumns: string[] 


  constructor(
    public dialog: MatDialog) {}

  ngOnInit() {
    this.displayedColumns = ['name', 'address', 'actions'];
    this.dataSource = new CustomerDataSource (this.paginator, this.sort,
     );

  }


  editCustomer(customer: CustomerListItem){
    const dialogRef = this.dialog.open(EditCustomerDialogComponent, <MatDialogConfig> {
      data: customer, 
    });


    dialogRef.afterClosed()
    .subscribe(result => {
      this.dataSource.data.push({name, address: ''})
      console.log('The dialog was closed');
      console.log(this.dataSource.data);
      
    });

  }

  deleteCustomer(customer: CustomerListItem){
    if(confirm('Are you sure you want to delete this customer?'))
    {
      this.dataSource.data = this.dataSource.data.filter(person => person.name != customer.name);
    }  
  }

  }

edit-customer-dialog.html

<h2 mat-dialog-title>
  Edit Customer
</h2>
<form *ngIf="form" [formGroup]="form" (ngSubmit)="onSubmitForm()">
<mat-dialog-content class="container">
  <mat-form-field>
      <input matInput placeholder="Name" formControlName ="name" required/>
  </mat-form-field>
  <mat-form-field class="input">
        <input id="placeholder" matInput placeholder="Address" formControlName ="address" required/>
    </mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
  <button
    id="add"
    mat-button
    mat-raised-button
    color="primary"
    type="submit"
  >
    Update
  </button>
  <button id="cancel" mat-button mat-raised-button color="warn" mat-dialog-close>Cancel</button>
</mat-dialog-actions>
</form>

edit-customer-dialog-comptent.ts

 import { Component, OnInit, Inject } from '@angular/core';
 import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
 import { MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog/';                                                                                                                                                                                                                                                                                                                                                                                                                                                  
 import {MatTableDataSource} from '@angular/material/table';
 import { MatPaginator } from '@angular/material/paginator';
 import { CustomerDataSource, CustomerListItem } from '../customer.datasource';

 @Component({
 selector: 'app-edit-customer-dialog',
 templateUrl: './edit-customer-dialog.component.html',
 styleUrls: ['./edit-customer-dialog.component.css']
 })

export class EditCustomerDialogComponent implements OnInit {
form: FormGroup;
customer: CustomerListItem [];


constructor(
 @Inject (MAT_DIALOG_DATA) public data: any,
 private dialogRef: MatDialogRef<EditCustomerDialogComponent>,
 private formBuilder: FormBuilder
 ) {}

ngOnInit() {
 // Intitlaize the form
 this.form = this.formBuilder.group({
   name: this.data.name, 
   address: this.data.address  
 })
 console.log(this.form.value);

}

onSubmitForm(){
 // Update Customer
 console.log(this.form.value);
 this.dialogRef.close(this.form.value);
}

}

datasource array:

export interface CustomerListItem {
    name: string;
    address: string;
  }
  
  // TODO: replace this with real data from server
  const EXAMPLE_DATA: CustomerListItem[] = [
    { name: 'Michael Jordan', address: '1111 Grail St. Concord MI 98076' },
    { name: 'Jeremy Scott', address: '7690 Wing Drive. Adidas, MI' },
    { name: 'Hiroki Nakamura', address: '980 Air Force Rd. Jubilee, MI' },
    { name: 'James Bond', address: '654 Depop Dr. Chicago, MI' },
    { name: 'Bill Bowerman', address: '1811 Hill St. Converse, MI' },
    { name: 'Clyde Frazier', address: '3333 Cement Ln. Jordan, MI'},
    { name: 'Jeff Staple', address: '4444 Black Cat Ct. Jordan,MI' },
    { name: 'Sophia Chang', address: '2006 Citrus Rd. Seven, MI'},
  ];
Nomee
  • 21
  • 3

1 Answers1

0

Add let i = index and pass i to the edit function


<td mat-cell *matCellDef="let row; let i = index;">
    <ng-container>
        <button id="edit" mat-icon-button color="primary" title="Update Customer" (click)="editCustomer(row, i)" >
            <mat-icon>edit</mat-icon>
        </button>
      
     </ng-container>
</td>
editCustomer(customer: CustomerListItem, i: number){
}

Try reinitializing the data after the edit.

this.dataSource.data[i] = result;
this.dataSource.data = this.dataSource.data;

OR

const temp = this.dataSource.data;
temp[i] = result;
this.dataSource.data = temp;
Lahar Shah
  • 7,032
  • 4
  • 31
  • 39
  • 1
    https://stackoverflow.com/questions/47581267/how-to-add-data-dynamically-to-mat-table-datasource/56948608#56948608 – Eliseo Jan 12 '21 at 06:56
  • @Lahar Shah thanks for the suggestion. However, this still doesn't insert the form data properly. When I do a `console.log(this.dataSource.data)` to show the updated data the array still shows no change. After reinitializing the table is not updated with the edited form data. – Nomee Jan 12 '21 at 07:21
  • @Eliseo thank you. This stackblitz was helpful for when I move on to adding data and not just editing existing data. However, I am trying to get the form data to insert into the array properly so that when I do render rows it shows the updated data. – Nomee Jan 12 '21 at 07:25
  • It looks like on edit the code is pushing the data to the array so it should be added to the end of the array and may not edit the data at the index! – Lahar Shah Jan 12 '21 at 07:25
  • @LaharShah Yes, you are right it is pushing to the end. Thanks! How would I get it to add to the index. Should index be included in the html as well? – Nomee Jan 12 '21 at 07:27
  • I see the name and address might be edited so yes you need to pass the index. You can have `*matCellDef="let row; let i = index;"` and pass the i to edit from HTML and use it to update it – Lahar Shah Jan 12 '21 at 07:32
  • @LaharShah, make a `@ViewChild(MatTable) table: MatTable;` so can makes a `table.renderRows()` after update the data . NOTE: Check before if result is null – Eliseo Jan 12 '21 at 07:48
  • Thanks @LaharShah i took into account your edits for index in the .html and .ts. Now I am getting both the correct edited data but also still getting empty data pushing to the end of the array. Instead of `this.datasource.data.push` how would I use something like `this.datasource.data.filter` to just create a new array and call that data? – Nomee Jan 12 '21 at 08:20
  • @Eliseo thank you i implemented the changes for the table and rendering that data. However, I am not seeing the table data updated although i can see the updated data when printing the array to the console. I am adding `table.renderRows()` inside the `addCustomer()` method after receiving the subscribed data. Would that be the correct place? – Nomee Jan 12 '21 at 08:25
  • @Nomee, your forked stackblitz:https://stackblitz.com/edit/angular-aynctq . See the "ViewChild". note: I used the same Dialog to Add and to Edit for simply – Eliseo Jan 12 '21 at 08:27
  • @Eliseo thank you! the render data is working now, thank you for forking it. I see you said you used the same dialog for add/edit. But I don't see where the `addCustomer()` is being called in the table-basic-example.ts code. since the click button in the html still calls that function. How is it grabbing the dialog? Thank you for your help! – Nomee Jan 12 '21 at 08:56
  • ::glups:: I forget save the last options "add". NOTE I just update the stackblitz and add code to show different message if insert or if update -it's only pass another variable to the dialog.data – Eliseo Jan 12 '21 at 09:06
  • @Eliseo Thanks for adding that. It makes perfect sense now. You have helped so much, thanks again! – Nomee Jan 12 '21 at 09:25