如何从双向绑定表单输入控件访问先前的值?

时间:2019-06-14 20:46:02

标签: javascript sql angular typescript two-way-binding

鉴于此处的表格,我希望能够更新SQL表中的数据。为了创建实现此目的所需的SQL查询,我必须同时传递上一行的值和新行的值以进行适当的比较。

SQL更新语句示例:

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

但是,由于我的输入使用双向绑定,因此在尝试将新值传递给SQL服务时,总是会得到新值。在发送更新之前,是否可以访问该行的先前值?

表单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>

组件TS文件:

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服务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);
            }
            )
        );
        }
    }

  }

1 个答案:

答案 0 :(得分:1)

再创建一个对象(例如prevValue),在其中存储值。该值应该是Deepcopy而不是浅表复制。请使用JSON.stringify和JSON.parse在对象中复制值。 例如,在newValue对象中存储新值,然后再分配新值,将newValue保存在prevValue中,这样您将拥有prevValue, 例如,如果您想要第一个值而不是不更新preValue