javascript - 如何从双向绑定表单输入控件访问先前的值?
问题描述
鉴于此处的表格,我希望能够更新 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);
}
)
);
}
}
}
解决方案
嗨,再创建一个对象(例如 prevValue)在其中存储值。应该是深拷贝而不是浅拷贝。使用 JSON.stringify 和 JSON.parse 在对象中复制值。例如,在 newValue 对象中,您存储新值,在分配新值之前,将 newValue 保存在 prevValue 中,这样您将拥有 prevValue,就像您想要第一个值而不是不更新 preValue
推荐阅读
- java - @SpringBootApplication 找不到 Bean
- c# - 返回视图/重定向到操作什么都不做
- dart - 调用 setState 后抽屉主体未更新
- java - 谷歌日历如何获取日期对象
- highcharts - 我可以使用 highchart 构建圆形热图吗
- google-cloud-platform - 谷歌云 SDK 安装错误:无法更新 [/Users/username/.bash_profile]。确保您对此位置具有写入权限
- javascript - npm 不断在全球范围内安装
- python - [0,0] 表达式有什么作用?
- python - 循环列以一次比较数据框中的两列,并根据每个比较结果添加一个汇总列
- ios - 构建失败并显示“命令 PrecompileSwiftBridgingHeader 失败,退出代码为非零”