大问题简短:基本上我想要实现的是将readonly
属性应用于FormControl
(文本框),就像以编程方式创建它一样。
完整方案:
我的Form
有一个FormRow
,其元素(FormGroup
s)部分是动态生成的。我也可以选择在点击按钮时添加一行。
我希望动态生成的FormGroup
个FormControl
s(文本框)为readonly
,但手动添加的FormControl
应该是可编辑的。
我怎样才能做到这一点?
<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>
在change
的文本框值上,我正在调用函数getAccountAssociatedDetails
,如您所见。如果有一些与输入值相关的详细信息,我将替换当前的FormGroup
并在行中添加更多FormGroup
。
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));
}
}
}
默认情况下,FormGroup
中的最后两个字段为readonly
。一旦用户在前两个字段中的任何一个字段中输入内容并聚焦,就应该获取与该值相关联的详细信息,替换当前FormGroup
并附加生成列表中的其他FormGroup
。我希望新添加的FormControl
中的所有FormGroup
都应为readonly
。用户可以添加更多字段,并重复该过程。
答案 0 :(得分:2)
根据这个:https://github.com/angular/angular/issues/11447,无法在表单控件上添加readonly
,只支持disabled
。
我甚至更喜欢disabled
,因为它在视觉上(灰色)显示用户无法触摸它。因此,当您想要禁用formcontrol时,只需使用:
formControlNameHere.disable();
或者如果您需要禁用整个表单组,可以使用
以相同的方式执行此操作myFormGroupNameHere.disable()
我们需要记住的是,这个formcontrol然后从表单对象中排除。要获取所有禁用的值,您需要调用:
this.myForm.getRawValue();
如果您确实要添加readonly
,则需要为其执行一些解决方法:https://stackoverflow.com/a/45452289/7741865:
[readonly]="anyBooleanPropertyFromComponent"
当然在那个答案中我们使用一个布尔值,这当然不适合你,然后我看到你需要设置一个额外的布尔形式控件,然后你可以用{{1}绑定}。但那只是为你的表单组添加一个新的“不必要”属性,所以另一个原因就是[readonly]
:)
希望这有帮助!