Skip to content
Advertisement

How to access a previous value from a two way binded form input control?

Given the form here, I would like to be able to Update data in a SQL Table. In order to create the SQL query needed to make this happen I’ll have to pass in both the previous row’s value and the new row’s value to make the proper comparison.

Example SQL Update Statement:

UPDATE MyTable 
SET column1 = new_value1, column2 = new_value2, 
WHERE column1 = oldValue1 AND column2 = oldValue2

Since my input is using two way binding however, I always get the new value when trying to pass it to my SQL service. Is there a way to access the row’s previous value prior to sending it for update?

Form HTML:

  <form #updateRowForm="ngForm" class="update-row-form">
            <table mdbTable #tableEl="mdbTable" class="table table-bordered
              table-responsive-md table-striped text-center">
              <thead>
                <tr>
                  <th *ngFor="let head of loadedTableData[0] | keys;">{{head}}</th>
                </tr>
              </thead>
              <tbody>
                <tr *ngFor="let item of loadedTableData; let i = index;">
                  <td *ngFor="let property of item | keys;"
                    class="form-group" #editRow>
                    <input #editRowProp mdbInput
                      [(ngModel)]="loadedTableData[i][property]"
                      (click)="updateValue(item)"
                      (ngModelChange)="changeValue($event, item)"
                      class="form-control"
                      [name]="property + '_' + i"
                      type="text">
                  </td>
                  <td>
                    <button type="button" mdbBtn class="btn btn-primary
                      rounded
                      btn-sm my-0"
                      (click)="updateRow(loadedTableData[i], item)">Update</button>
                    <hr>
                    <button type="button" mdbBtn class="btn btn-danger
                      rounded
                      btn-sm my-0" (click)="deleteRow(item)">Remove</button>
                  </td>
                </tr>
              </tbody>
            </table>
          </form>

Component TS file:

import { Component, OnInit, ViewChild, ViewChildren, QueryList, OnDestroy } from 
'@angular/core';
import { SqlService } from '../services/sql.service';
import { MdbTablePaginationComponent, MdbTableDirective } from 'angular-bootstrap-md';
import { NgForm, FormGroup } from '@angular/forms';
import { Subscription, BehaviorSubject } from 'rxjs';
import { MatSnackBar } from '@angular/material';
import { SuccessComponent } from '../snackbar/success/success.component';
import { ErrorComponent } from '../snackbar/error/error.component';
import { ConfirmComponent } from '../snackbar/confirm/confirm.component';

@Component({
  selector: 'app-data-table',
  templateUrl: './data-table.component.html',
  styleUrls: ['./data-table.component.scss']
})
export class DataTableComponent implements OnInit, OnDestroy {
  @ViewChild(MdbTablePaginationComponent) mdbTablePagination: 
  MdbTablePaginationComponent;
  @ViewChild(MdbTableDirective) mdbTable: MdbTableDirective;
  @ViewChild('addRowForm') addRowForm: NgForm;
  @ViewChildren('prop') addRowProps: QueryList<any>;
  @ViewChild('editRowForm') editRowForm: NgForm;
  @ViewChild('editRow') editRow: FormGroup;

  public loadedTableData: any = [];
  public previousTableData: any = [];
  public displayedColumns: any = [];
  public tableHasBeenLoaded = false;
  public rowBeingEdited: BehaviorSubject<any> = new BehaviorSubject<any>({});
  public rowPreviousValue: BehaviorSubject<any> = new BehaviorSubject<any>({});
  public currentTableData: any = {};
  public rowsAffected = 0;

  public elements: string[] = [];
  public previous: any;

  private subscriptions: Subscription[] = [];

  constructor(private sqlService: SqlService,
              private snackBar: MatSnackBar) { }

  public ngOnInit(): void {
    this.subscriptions.push(
      this.sqlService.tableHasBeenLoaded.subscribe(data => {
        this.tableHasBeenLoaded = data;
      }),

  this.sqlService.tableHasBeenLoaded.subscribe(data => {
       this.tableHasBeenLoaded = data;
  }),

  this.sqlService.currentTableData.subscribe(data => {
    this.currentTableData = data;
  }),

  this.sqlService.rowsAffected.subscribe(data => {
    this.rowsAffected = data;
      })
    );
  }

  public updateRow(newRowValue: any, previousRowValue: any): void {

    // Both of these values are the same.
    console.log(newRowValue, ' << initialRow');
    console.log(previousRowValue, ' <<previousRowVal')



    const updateData = {
      previousRowValue,
      newRowValue
    };

    this.subscriptions.push(
      this.sqlService.updateTableData(updateData)
        .subscribe((resp) => {
        console.log(resp, ' << update response');
        // this.sqlService.currentDataView.next(resp);
        if (resp) {
          this.snackBar.openFromComponent(ConfirmComponent, {
            duration: 3000,
            data: this.rowsAffected
          });
        }
      })
     );

  }

  public ngOnDestroy(): void {
    for (const sub of this.subscriptions) {
      sub.unsubscribe();
    }
  }

}

SQL Service TS:

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import { tap } from 'rxjs/operators';
    import { Observable, BehaviorSubject } from 'rxjs';
    import { ITableList } from '../interfaces/ITableList.interface';

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

    private uri = 'http://localhost:8080';
    private headers = new HttpHeaders({ 'Content-Type': 'application/json; charset=utf-8' });

    public currentDataView: BehaviorSubject<any> = new BehaviorSubject<any>([]);
    public currentTableData: BehaviorSubject<any> = new BehaviorSubject<any>({});
    public tableHasBeenLoaded: BehaviorSubject<any> = new BehaviorSubject<boolean>(false);
    public rowsAffected: BehaviorSubject<number> = new BehaviorSubject<number>(0);

    constructor(private http: HttpClient) { }

    public updateTableData(updateData: any): Observable<any> {
        const parsedData = JSON.parse(JSON.stringify(updateData));

        if (updateData) {
        return this.http.post(`${this.uri}/api/updateTableData`, parsedData).pipe(
            tap(
            response => {
                this.rowsAffected.next(response.rowsAffected);
            },
            error => {
                throw new Error(error);
            }
            )
        );
        }
    }

  }

Advertisement

Answer

hi create one more object(e.g prevValue) store value in it.that should be deepcopy not shallow copy.. use JSON.stringify and JSON.parse to copy value in object. e.g In newValue object you store the new value, before assigning the new value, save newValue in prevValue, by this you will have prevValue, like if you want first value than don’t update preValue

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement