Issue
The validator works perfectly with required. But I need the unique validator, to check if the labels has duplicate names.
When I switch to unique in inventory.component.ts the table isn't even showing up correctly.
inventory.component.ts:
this.formBuilder.control(item['inventoryName'], RxwebValidators.unique())
// this.formBuilder.control(item['inventoryName'], Validators.required)
I noticed, that all other examples on stackoverflow and docs are using RxwebValidators.unique() with an extra key.
addSkill(){
let skillsArray = <FormArray>this.employeeFormGroup.controls.skills;
skillsArray.push(this.getSkillFormGroup());
}
getSkillFormGroup(){
// extra skillName key
return this.formBuilder.group({
skillName:['',RxwebValidators.unique()]
})
}
Is this somehow a requirement? https://docs.rxweb.io/form-validations/unique/validators
Complete code:
inventory.html:
<p>Inventory Form Value: {{ inventoryForm.value | json }}</p>
<p>Form Status: {{ inventoryForm.status }}</p>
<div *ngIf="!inventoryForm.valid">
<mat-card style="text-align: center; background-color:#ea8288">
<mat-card-content>Inventory invalid</mat-card-content>
</mat-card>
</div>
<form [formGroup]="inventoryForm">
<div class="table-container">
<table
mat-table
class="mat-elevation-z8"
[dataSource]="inventorySource"
formArrayName="inventoryFormArr"
>
<!-- ref.: https://stackoverflow.com/questions/51150193/angular-material-editable-table-using-formarray -->
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr
mat-row
*matRowDef="let row; let i = index; columns: displayedColumns"
></tr>
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Name Column -->
<ng-container matColumnDef="inventoryName">
<th mat-header-cell *matHeaderCellDef>Name</th>
<td
mat-cell
*matCellDef="
let inventoryFormArr of inventoryFormArr.controls;
let i = index
"
>
<mat-form-field appearance="outline" style="margin-bottom: -1.25em">
<input
matInput
autocorrect="off"
autocapitalize="off"
spellcheck="off"
type="text"
required
type="text"
[formControlName]="i"
/>
</mat-form-field>
</td>
</ng-container>
<!-- Quantity Column -->
<ng-container matColumnDef="quantity">
<th mat-header-cell *matHeaderCellDef>Quantity</th>
<td mat-cell *matCellDef="let element">{{ element.quantity }}</td>
</ng-container>
</table>
</div>
</form>
inventory.component.ts:
import { Component } from '@angular/core';
import { FormArray, FormBuilder } from '@angular/forms';
import { Validators } from '@angular/forms';
import { RxwebValidators } from '@rxweb/reactive-form-validators';
export interface myDataArray {
inventoryName: string;
quantity: number;
}
const ELEMENT_DATA: myDataArray[] = [
{ inventoryName: 'Cars', quantity: 14 },
{ inventoryName: 'Books', quantity: 49 },
];
@Component({
selector: 'inventory-table',
templateUrl: './inventory.component.html',
styleUrls: ['./inventory.component.scss'],
})
export class InventoryComponent {
displayedColumns: string[] = ['inventoryName', 'quantity'];
inventorySource = ELEMENT_DATA;
inventoryForm = this.formBuilder.group({
inventoryFormArr: this.formBuilder.array([]),
});
constructor(private formBuilder: FormBuilder) {}
get inventoryFormArr() {
return this.inventoryForm.get('inventoryFormArr') as FormArray;
}
ngOnInit(): void {
this.inventorySource.forEach((item) => {
this.inventoryFormArr.push(
//this.formBuilder.control(item['inventoryName'], RxwebValidators.unique())
this.formBuilder.control(item['inventoryName'], Validators.required)
);
});
}
}
Solution
Its not able to handle an array of formControls, looks like a bug in the validator, not sure.
In the meantime, as a workaround, you can just create a formArray of formGroups, and the validation seems to work fine!
html
<p>Inventory Form Value: {{ inventoryForm.value | json }}</p>
<p>Form Status: {{ inventoryForm.status }}</p>
<div *ngIf="!inventoryForm.valid">
<mat-card style="text-align: center; background-color:#ea8288">
<mat-card-content>Inventory invalid</mat-card-content>
</mat-card>
</div>
<form [formGroup]="inventoryForm">
<div class="table-container">
<table
mat-table
class="mat-elevation-z8"
[dataSource]="inventorySource"
formArrayName="inventoryFormArr"
>
<!-- ref.: https://stackoverflow.com/questions/51150193/angular-material-editable-table-using-formarray -->
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr
mat-row
*matRowDef="let row; let i = index; columns: displayedColumns"
></tr>
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Name Column -->
<ng-container matColumnDef="inventoryName">
<th mat-header-cell *matHeaderCellDef>Name</th>
<td
mat-cell
*matCellDef="
let inventoryFormArr of inventoryFormArr.controls;
let i = index
"
[formGroupName]="i"
>
<mat-form-field appearance="outline" style="margin-bottom: -1.25em">
<input
matInput
autocorrect="off"
autocapitalize="off"
spellcheck="off"
type="text"
required
type="text"
formControlName="inventoryName"
/>
</mat-form-field>
</td>
</ng-container>
<!-- Quantity Column -->
<ng-container matColumnDef="quantity">
<th mat-header-cell *matHeaderCellDef>Quantity</th>
<td mat-cell *matCellDef="let element">{{ element.quantity }}</td>
</ng-container>
</table>
</div>
</form>
ts
import { Component } from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
import { Validators } from '@angular/forms';
import { RxwebValidators } from '@rxweb/reactive-form-validators';
export interface myDataArray {
inventoryName: string;
quantity: number;
}
const ELEMENT_DATA: myDataArray[] = [
{ inventoryName: 'Cars', quantity: 14 },
{ inventoryName: 'Books', quantity: 49 },
];
@Component({
selector: 'inventory-table',
templateUrl: './inventory.component.html',
styleUrls: ['./inventory.component.scss'],
})
export class InventoryComponent {
displayedColumns: string[] = ['inventoryName', 'quantity'];
inventorySource = ELEMENT_DATA;
inventoryForm = this.formBuilder.group({
inventoryFormArr: this.formBuilder.array([]),
});
constructor(private formBuilder: FormBuilder) {}
get inventoryFormArr() {
return this.inventoryForm.get('inventoryFormArr') as FormArray;
}
ngOnInit(): void {
this.inventorySource.forEach((item) => {
this.inventoryFormArr.push(
//this.formBuilder.control(item['inventoryName'], RxwebValidators.unique())
new FormGroup({
inventoryName: this.formBuilder.control(item['inventoryName'], [
Validators.required,
RxwebValidators.unique(),
]),
})
);
});
}
}
Answered By - Naren Murali
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.