[英]FormArray in Angular Reactive Form not resetting on form submit
[英]Angular Column level filters in table having reactive form and formArray
我想實現高度動態的表格,其中應用了列級過濾器,並實現了對表格的每個單元格應用驗證的可編輯行。
我已經實現了帶有可編輯行和動態驗證的動態表格顯示。 但是在使用列級過濾器時苦苦掙扎。
我的問題陳述:
headers = ['name','age']
和數據[{name:'abc',age:'xyz'},{name:'pqr',age:'xyz'}, ..]
通過上述設置,我已經使用 formArray 實現了反應式表單。
示例設置是在stackblitz 中創建的
這是我的表格:
<form [formGroup]="data_form">
<table class="table table-border">
<thead>
<tr>
<th>
name
</th>
<th>
age
</th>
<th><button class="btn btn-primary ">Save</button></th>
</tr>
<tr>
<th *ngFor="let th of rowKeys">
<ng-container *ngIf="th !=='isEditable'">
<input type="text" formControlName="{{th}}" />
</ng-container>
</th>
<th></th>
</tr>
</thead>
<tbody formArrayName="persons">
<ng-container *ngFor="let item of persons.controls;let j = index">
<tr [formGroupName]="j">
<ng-container *ngIf="!item.value.isEditable; else editable">
<td>{{ item.value.name }}</td>
<td>{{ item.value.age }}</td>
</ng-container>
<ng-template #editable>
<td><input formControlName="name" /></td>
<td><input formControlName="age" /></td>
</ng-template>
<td>
<button (click)="toggleEdit(j)">
{{ !item.value.isEditable ? "Edit": "Cancel"}}
</button>
</td>
</tr>
</ng-container>
</tbody>
</table>
</form>
<h2>
{{data_form.status}}
</h2>
和:
import { Component } from "@angular/core";
import {
FormArray,
FormBuilder,
FormControl,
FormGroup,
Validators
} from "@angular/forms";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "Angular";
constructor(private fb: FormBuilder) {}
patterns = [
/^[.\d]+$/,
/^(yes|no)$/i,
/^[a-zA-Z0-9 _/]+$/,
/^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/
];
data = [
{
name: "Sachin",
age: 27,
isEditable: false
},
{
name: "Gopal",
age: 27,
isEditable: false
},
{
name: "Pankaj",
age: 24,
isEditable: false
}
];
rowKeys = Object.keys(this.data[0]);
keys = [...new Set(this.data.map(item => Object.keys(item)).flat())];
keyPattern = this.keys.map(item => ({
key: item,
pattern: this.patterns.find(pattern =>
this.data.every(i => pattern.test(i[item]))
)
}));
data_form = this.fb.group({
persons: this.fb.array(
this.data.map(item =>
this.fb.group(
this.keyPattern.reduce(
(prev, { key, pattern }) => ({
...prev,
[key]: [
item[key],
[Validators.required, Validators.pattern(pattern)]
]
}),
{}
)
)
)
)
});
get persons(): FormArray {
return this.data_form.get("persons") as FormArray;
}
toggleEdit(j) {
const currentEditStatus = this.persons.controls[j].get("isEditable").value;
this.persons.controls[j].get("isEditable").setValue(!currentEditStatus);
}
ngOnInit(){
this.rowKeys.forEach((num) => {
if (num == "isEditable") return;
const fc = new FormControl('');
this.data_form.addControl(num, fc)
});
/**
* How to filter formsArray ?
*/
// this.data_form.get('cuisp').valueChanges.pipe(
// debounceTime(100),
// distinctUntilChanged(),
// ).subscribe(val => {
// console.log(val)
// const result = this.persons.value.filter(res => {
// if (res['cuisp'] === val) {
// return res
// }
// });
// this.persons.patchValue(result)
// console.log(result)
// });
}
}
如何實現列級搜索,那么當我在 Name 列中搜索時,應顯示相應的名稱。
考慮以下使用反應式編程的方法。
步驟如下
Subject
以用作過濾的觸發器rxjs
的combineLatest([...])
運算符組合數據和主題下面是一個工作代碼, this demo on stackblitz
看到this demo on stackblitz
constructor(private fb: FormBuilder) {}
patterns = [
/^[.\d]+$/,
/^(yes|no)$/i,
/^[a-zA-Z0-9 _/]+$/,
/^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/
];
data$ = of([
{
name: "Sachin",
age: 27,
isEditable: false
},
{
name: "Gopal",
age: 27,
isEditable: false
},
{
name: "Pankaj",
age: 24,
isEditable: false
}
]);
filterStringSubject$ = new BehaviorSubject({});
filterStringAction$ = this.filterStringSubject$.asObservable();
filterString$ = this.filterStringAction$.pipe(
map(stringObject =>
Object.entries(stringObject).map(item => ({
key: item[0],
value: item[1]
}))
)
);
rowKeys$ = this.data$.pipe(
map(data => Object.keys(data[0])),
tap(rowKeys => {
rowKeys.forEach(num => {
if (num == "isEditable") return;
this.filterStringSubject$.next({
...this.filterStringSubject$.value,
[num]: ""
});
});
})
);
keys$ = this.data$.pipe(
map(data => [...new Set(data.map(item => Object.keys(item)).flat())])
);
keyPattern$ = combineLatest(this.keys$, this.data$).pipe(
map(([keys, data]) => {
return keys.map(item => ({
key: item,
pattern: this.patterns.find(pattern =>
data.every(i => pattern.test(i[item]))
)
}));
})
);
data_form: FormGroup;
dataFiltered$ = combineLatest([this.data$, this.filterString$]).pipe(
map(([data, filterString]) =>
this.persons?.value.filter(item =>
filterString.every(a => `${item[a.key]}`.includes(`${a.value}`))
)
)
);
dataForm$ = combineLatest([ this.data$,
this.keyPattern$]).pipe(
tap(([data, keyPattern]) => {
this.data_form = this.fb.group({
persons: this.fb.array(
data.map(item =>
this.fb.group(
keyPattern.reduce(
(prev, { key, pattern }) => ({
...prev,
[key]: [
item[key],
[Validators.required, Validators.pattern(pattern)]
]
}),
{}
)
)
)
)
});
}),
)
v$ = combineLatest([
this.dataForm$,
this.rowKeys$,
this.filterString$,
this.dataFiltered$
]).pipe(
map(([, rowKeys, filterString, dataFiltered]) => ({
rowKeys,
filterString,
dataFiltered
}))
);
get persons(): FormArray {
return this.data_form?.get("persons") as FormArray;
}
toggleEdit(j) {
const currentEditStatus = this.persons.controls[j].get("isEditable").value;
this.persons.controls[j].get("isEditable").setValue(!currentEditStatus);
}
filterBy(item, value) {
this.filterStringSubject$.next({
...this.filterStringSubject$.value,
[item]: value
});
}
ngOnInit() { }
在你的 HTML
<form [formGroup]="data_form" *ngIf='v$ | async as v'>
<table class="table table-border">
<thead>
<tr>
<th>
name
</th>
<th>
age
</th>
<th><button class="btn btn-primary ">Save</button></th>
</tr>
<tr>
<td *ngFor="let item of v.rowKeys">
<input *ngIf='item != "isEditable"' type="text"
(input)="filterBy(item, $event.target.value)" />
</td>
<th></th>
</tr>
</thead>
<tbody formArrayName="persons">
<ng-container *ngFor="let item of v.dataFiltered;let j = index">
<tr [formGroupName]="j">
<ng-container *ngIf="!persons.controls[j]?.get('isEditable').value; else editable">
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
</ng-container>
<ng-template #editable>
<td><input formControlName="name" /></td>
<td><input formControlName="age" /></td>
</ng-template>
<td>
<button (click)="toggleEdit(j)">
{{ !persons.controls[j]?.get('isEditable').value ? "Edit": "Cancel"}}
</button>
</td>
</tr>
</ng-container>
</tbody>
</table>
</form>
<h2>
{{data_form?.status}}
</h2>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.