Big question short: Basically what I want to achieve is, to apply readonly
attribute to FormControl
(textbox), right when it's created programmatically.
Full scenario:
I have a Form
that has a FormRow
whose elements (FormGroup
s) are partly generated dynamically. I also have given an option to append a row on click of a button.
I want the FormGroup
's FormControl
s (textboxes) that are generated dynamically to be readonly
, but the manually added FormControl
s should be editable.
How can I achieve this?
<div formArrayName="rows">
<div class="row" *ngFor="let row of detailForm.get('rows').controls; let i = index" [formGroupName]="i">
<div class="col-xs-1 text-center">
<input type="checkbox" [(ngModel)]="detailSelected[i]" [ngModelOptions]="{standalone: true}">
</div>
<div class="col-xs-2">
<input type="text" class="form-control" formControlName="account" (change)="getAccountAssociatedDetails(detailForm.get(['rows', i, 'account']), 'account', i)">
</div>
<div class="col-xs-2">
<input type="text" class="form-control" formControlName="detailNo" (change)="getAccountAssociatedDetails(detailForm.get(['rows', i, 'detailNo']), 'detail', i)">
</div>
<div class="col-xs-4">
<input type="text" class="form-control" readonly formControlName="detailName">
</div>
<div class="col-xs-3">
<input type="text" class="form-control" readonly formControlName="detailCountry">
</div>
</div>
</div>
On change
of textbox value, I'm calling the function getAccountAssociatedDetails
, as you can see. If there are some details associated with the value entered, I'm replacing that current FormGroup
and adding some more FormGroup
s to the row.
getAccountAssociatedDetails(control: FormControl, type: string, index: number) {
let value = control.value;
if (!!value) {
let form = this.detailForm;
control.setErrors({
'alreadyEntered': null
});
if (type === 'detail') {
if (this.detailAlreadyEnteredManually.detailNo.includes(value)) {
control.setErrors({
'alreadyEntered': true
});
}
} else if (type === 'account') {
if (this.detailAlreadyEnteredManually.accountNumber.includes(value)) {
control.setErrors({
'alreadyEntered': true
});
}
}
// if detail or account is already entered dont call service
if (!control.hasError('alreadyEntered')) {
this.agreementDetailsService.getdetails(value, type)
.subscribe(response => {
let associatedDetailsArray = < Array < any >> response;
if (!!associatedDetailsArray) {
let rows = < FormArray > form.get('rows');
// if search mode is 'detail'
if (type === 'detail') {
if (!this.detailAlreadyEnteredManually.detailNo.includes(value)) {
rows.setControl(index, this.builddetailItem(associatedDetailsArray[0].accountNumber.value, value, associatedDetailsArray[0].detailName, associatedDetailsArray[0].detailCountry));
this.detailAlreadyEnteredManually.detailNo.push(value);
for (let i = 1; i < associatedDetailsArray.length; i++)
rows.insert(index + i, this.builddetailItem(associatedDetailsArray[i].accountNumber.value, value, associatedDetailsArray[i].detailName, associatedDetailsArray[i].detailCountry));
}
//if search mode is 'account'
} else if (type === 'account') {
if (!this.detailAlreadyEnteredManually.accountNumber.includes(value)) {
rows.setControl(index, this.builddetailItem(value, associatedDetailsArray[0].detailNo.value, associatedDetailsArray[0].detailName, associatedDetailsArray[0].detailCountry));
this.detailAlreadyEnteredManually.accountNumber.push(value);
for (let i = 1; i < associatedDetailsArray.length; i++)
rows.insert(index + i, this.builddetailItem(value, associatedDetailsArray[i].detailNo.value, associatedDetailsArray[i].detailName, associatedDetailsArray[i].detailCountry));
}
}
}
},
error => console.log(error));
}
}
}
The last two fields in the FormGroup
are readonly
by default. Once the user enters something in either of the first two fields and focuses out, the details associated with that value should be fetched, the current FormGroup
is replaced and other FormGroup
s in the generated list are appended. I want all the FormControl
s in those newly added FormGroup
s should be readonly
. The user can add more fields and the process repeats.