问题
I am using reactive forms formArray to add the section of data on click of add, and on click of edit, after editing i have used delete and save button to save to the table. So basically one operation at a time must be done. So, when i click on edit, Add New button will be disabled and after saving the data, i am enabling the Add button. So, now if i have made changes in the item by using edit, and click to delete or take up a new item to edit, then alert message must throw up saying, you want to delete changes made so far. I am trying to implement but it works only for the first time and from next time it start showing alert message for every click on edit icon. Can anyone help me out to make it work.
DEMO: DEMO
HTML of Table to where i am pushing data and displaying what i have added and what items i am getting from backend.
<table class="table table-hover accordion-table"
*ngIf="agentDetailsList?.w9Info || temporaryControls.length != 0">
<thead>
<tr>
<th scope="col" *ngFor="let field of w9ListDetails"> {{field.displayName}}
</th>
<th scope="col" class="width75">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let w9 of agentDetailsList?.w9Info ? agentDetailsList.w9Info : temporaryControls ">
<td *ngFor="let field of w9ListDetails">
{{w9[field.param]}}
</td>
<td class="width75">
<button type="button" class="btn btn-outline-primary btn-table {{isReadOnly ? 'link-disabled' : ''}}"
title="View" (click)="downLoadFiles(w9)"><i class="fas fa-eye"></i></button>
<button type="button" class="btn btn-outline-primary btn-table ml-1 {{isReadOnly ? 'link-disabled' : ''}}"
title="Edit" (click)="editw9(w9, 'editMode')"><i class="fas fa-edit"></i></button>
</td>
</tr>
</tbody>
</table>
HTML of formArray:
<div class="card-body" *ngIf="agentW9InfoForm" [formGroup]='agentW9InfoForm'>
<form formArrayName="w9Info" *ngFor="let item of agentW9InfoForm.controls.w9Info?.controls; let i = index;">
<div class="border rounded p-3 position-relative" [formGroupName]="i">
<button class="btn btn-link btn-close position-absolute" (click)="deleteW9Details(i,item)"
[class.disabled]="isReadOnly"><i class="fas fa-times fa-lg"></i></button>
<div class="row">
<div class="col-6">
<div class="form-group">
<label for="">Tax ID Number <span class="text-danger">*</span></label>
<input type="text" class="form-control {{w9ReadOnly ? 'link-disabled' : ''}}"
placeholder="Tax ID Number" name="taxId" formControlName="taxId" maxlength="50"
autocomplete="new-tx" [ngClass]="{ 'is-invalid': submitted && item.controls.taxId.errors }"
allowNumberOnly>
<div *ngIf="submitted && item.controls.taxId.errors" class="invalid-feedback">
<div *ngIf="item.hasError('required', 'taxId')">Tax Id is required</div>
</div>
</div>
</div>
<div class="col-6">
<div class="form-group">
<label for="">Signature Date <span class="text-danger">*</span></label>
<input type="text" class="form-control {{w9ReadOnly ? 'link-disabled' : ''}}" placeholder="MM/DD/YYYY"
name="signatureDate" formControlName="signatureDate"
[ngClass]="{ 'is-invalid': submitted && item.controls.signatureDate.errors }">
<div *ngIf="submitted && item.controls.signatureDate.errors" class="invalid-feedback">
<div *ngIf="item.controls.signatureDate.errors.required">Signature Date is required</div>
</div>
</div>
</div>
<div class="col-6">
<div class="form-group ">
<label for="">Business Type <span class="text-danger">*</span></label>
<select class="custom-select {{w9ReadOnly ? 'link-disabled' : ''}}" name="businessType"
formControlName="businessType"
[ngClass]="{ 'is-invalid': submitted && item.controls.businessType.errors }">
<option value=''>Select Business Type </option>
<option *ngFor="let businessType of detailsSelectDropDown?.W9BusinessType"
[value]='businessType.id'>
{{businessType.value}}</option>
</select>
<div *ngIf="submitted && item.controls.businessType.errors" class="invalid-feedback">
<div *ngIf="item.controls.businessType.errors.required">Business Type is required</div>
</div>
</div>
</div>
</div>
<div class="row" *ngIf="!hideUpload">
<div class="col">
<div class="form-group" >
<label for="">Upload File</label>
<div class="form-control" (click)="fileInput.click()" appDragDrop
(onFileDropped)="uploadFile($event,item.controls)">
<input hidden type="file" #fileInput (change)="uploadFile($event,item.controls)"
class="custom-file-input" id="uploadFile" formControlName="fileName">
<span>{{ item.controls.fileName.value?.slice(12) }}</span>
</div>
</div>
</div>
<div class="col-6">
<button type="button" class="btn btn-outline-primary mt-4" id="" (click)="upload()">Upload</button>
</div>
</div>
<div class="row">
<div class="col d-flex justify-content-end align-items-end">
<button class="btn btn-primary delbtn" (click)="saveW9Details(item.controls,i)"
[class.disabled]="isReadOnly">
Save
</button>
</div>
</div>
</div>
</form>
<div class="row mt-3">
<div class="col d-flex justify-content-end align-items-end">
<div class="form-group {{addButtonDisable ? 'link-disabled' : ''}}">
<button type="button" class="btn btn-outline-primary {{isReadOnly ? 'link-disabled' : ''}}"
(click)="addW9Details()"><i class="fas fa-plus"></i> Add New</button>
</div>
</div>
</div>
</div>
TS:
deleteW9Details(i) {
let error = !this.getFormData.invalid && this.getFormData.dirty
if(!error == true) {
this.getFormData.removeAt(i);
} else {
alert('are you sure to delete')
}
}
HTML:
<button class="col-2 pull-left m-b10 m-t10 delbtn" (click)="deleteW9Details(i)"
[class.disabled]="isReadOnly">
Delete
</button>
<button class="col-2 pull-left m-b10 m-t10 delbtn" (click)="saveW9Details(item.controls)"
[class.disabled]="isReadOnly">
Save
</button>
TS of FormArray:
private w9InfoFormInit() {
if (!this.groupCode && !this.agentCode) {
// Add
this.agentW9InfoForm = this.FB.group({
w9Info: this.FB.array([this.createW9Information()])
})
} else {
//edit
this.agentW9InfoForm = this.FB.group({
w9Info:this.FB.array([])
})
}
if (this.mode == 1) {
this.agentW9InfoForm.disable()
this.isReadOnly = true;
}
}
editw9InfoDetails(w9,mode) {
let modes = mode
if("editMode" ) {
this.hideUpload = true;
this.saveUpload = false
} else {
this.hideUpload = false;
this.saveUpload =true
}
this.addButtonDisable = true;
const control = <FormArray>this.agentW9InfoForm.get('w9Info');
control.controls = [];
let info = [];
info.push(w9)
for (const emp of info) {
const grp = this.FB.group({
taxId: [emp.taxId, Validators.required],
signatureDate: [emp.signatureDate, [Validators.required]],
businessType: [emp.businessType, [Validators.required]],
fileName:[emp.fileName],
agentW9id:[emp.agentW9id],
originalFileName: [emp.originalFileName],
agentCode:[emp.agentCode],
id:[emp.id]
});
control.push(grp);
}
}
editw9(w9,mode) {
let error = !this.w9InfoDetails.invalid && this.w9InfoDetails.dirty
if(error != true) {
this.editw9InfoDetails(w9,mode)
} else {
this.notificationService.activate("Validation Message", "Are you sure to delete changes? ", "Yes").then(responseOK => {
if (responseOK) {
this.editw9InfoDetails(w9,mode)
}
});
}
}
Craeting of form Array along with delete and edit of the row items,
public addW9Details() {
this.hideUpload = false;
this.w9ReadOnly = false;
if(this.agentDetailsList && this.agentDetailsList.w9Info) {
this.saveUpload = false;
} else {
this.saveUpload = true;
}
const control = <FormArray>this.agentW9InfoForm.get('w9Info');
if(this.agentDetailsList && this.agentDetailsList.w9Info) {
control.controls = [];
}
control.push(this.createW9Information());
this.addButtonDisable = true;
}
public deleteW9Details(i,item) {
let error = !this.w9InfoDetails.invalid && this.w9InfoDetails.dirty
if(!error == true) {
this.w9InfoDetails.removeAt(i);
this.addButtonDisable = false
} else {
this.notificationService.activate("Validation Message", "Are you sure to delete changes? ", "Yes").then(responseOK => {
if (responseOK) {
this.w9InfoDetails.removeAt(i);
this.addButtonDisable = false
}
});
}
}
public preventW9DetailsEmpty() {
if (!this.w9InfoDetails.length) {
let group = this.createW9Information();
group.reset();
this.agentW9InfoForm.setControl('w9Info', this.FB.array([group]));
}
}
public get w9InfoDetails(): FormArray {
return <FormArray>this.agentW9InfoForm.controls['w9Info'];
}
private createW9Information() {
return this.FB.group({
taxId: [null, Validators.required],
signatureDate: [null, Validators.required],
businessType: [null, Validators.required],
originalFileName: [''],
agentW9id:0,
fileName: [''],
agentCode:parseInt(this.agentbasicInfoForm.controls['agentCode'].value),
id:''
});
}
Saving of newly added row item/save of edit item to grid both part code contains here:
saveW9Details(item, num) {
if(this.w9InfoDetails.invalid) {
this.notificationService.activate("Validation Message", "Please fill Tax Id Number,Signature Date, Business Type", "OK", false).then(responseOK => {
if (responseOK) {
}
});
} else {
this.addButtonDisable = false;
if(this.agentDetailsList && this.agentDetailsList.w9Info) {
if(item.agentW9id.value) {
for(var i=0;i<this.agentDetailsList.w9Info.length;i++){
let itembusinessName = this.detailsSelectDropDown.W9BusinessType.filter(x => x.id === parseInt(item.businessType.value));
if(this.agentDetailsList.w9Info[i].agentW9id===item.agentW9id.value){
this.agentDetailsList.w9Info[i].taxId=item.taxId.value;
this.agentDetailsList.w9Info[i].businessType=item.businessType.value;
this.agentDetailsList.w9Info[i].signatureDate=item.signatureDate.value;
this.agentDetailsList.w9Info[i].agentW9id = item.agentW9id.value;
this.agentDetailsList.w9Info[i].businessName = itembusinessName[0].value;
this.agentDetailsList.w9Info[i].id = itembusinessName[0].id;
// updated=true;
this.temporaryControls.push(this.agentDetailsList.w9Info[i])
}
}
}
else {
let itembusinessName = this.detailsSelectDropDown.W9BusinessType.filter(x => x.id === parseInt(item.businessType.value));
console.log(itembusinessName,"business")
let temp={
taxId:item.taxId.value,
signatureDate:item.signatureDate.value,
businessType: item.businessType.value,
agentW9id:item.agentW9id.value,
businessName: itembusinessName[0].value,
originalFileName:item.fileName.value?item.fileName.value.slice(12):'',
id: this.temporaryControls.length
}
if(this.agentDetailsList&& this.agentDetailsList.w9Info) {
this.agentDetailsList.w9Info.push(temp);
this.temporaryControls.push(temp)
}
console.log(this.temporaryControls,"dssdf")
}
}
else {
let itembusinessName = this.detailsSelectDropDown.W9BusinessType.filter(x => x.id === parseInt(item.businessType.value));
console.log(itembusinessName,"business")
let temp={
taxId:item.taxId.value,
signatureDate:item.signatureDate.value,
businessType: item.businessType.value,
agentW9id:item.agentW9id.value,
businessName: itembusinessName[0].value,
originalFileName:item.fileName.value?item.fileName.value.slice(12):'',
id: this.temporaryControls.length
};
console.log(temp,"dsfdsg")
this.temporaryControls.push(temp)
}
console.log(this.temporaryControls,"dssdf")
this.w9InfoDetails.removeAt(item);
console.log(this.temporaryControls,"temp")
}
}
回答1:
On edit method editw9(), you are getting message 'are you sure to delete', because after edit and save for the first time, "error" is always getting set to true from next edit click onwards, it is because this.getFormData.dirty is returning true.
let error = !this.getFormData.invalid && this.getFormData.dirty
On save method call this.getFormData.markAsPristine();
as last line, which will reset dirty flag of the form
来源:https://stackoverflow.com/questions/59992013/how-to-throw-validation-message-when-there-is-some-change-in-the-edit-item-usin