使用 Angular 8 和 Formbuilder 在 View 中切換 FormControl(Typescript)
我如何使用 Typescript,而不是 HTML,從 HTML DOM 視圖中移除帶有 NgIf 的元素?尋找類似的語法。
在 TypeScript 中更喜歡遍歷陣列,並從視圖中移除項目,而不是用 NgIf 包裹所有 20 個表單控制,這樣感覺有點重複。
目前使用的是 Formbuilder,而不是 FormArray。這個連結會將樣式設為 display none,但據我所讀,這在 Angular 中並不是理想做法。這是真的嗎?
Angular 2 -> 如何使用 FormGroup 隱藏控制項
我們有排除陣列,並且偏好在 Typescript 中用 foreach 來禁用
可能像這樣嗎?
這僅僅是禁用該欄位,但仍會在 HTML 檢視中顯示
Object.keys(this.customerForm.controls).forEach(key => {
if (this.excludeFormControlArray.indexOf(key) >= 0) {
this.customerForm.get(key).disable; // This only disables the field, still shows in html View
this.customerForm = this.formBuilder.group({
'firstName': [null, [Validators.maxLength(50), PhoneNumberValidator]],
'phoneNumber': [null, [Validators.maxLength(50), PhoneNumberValidator]],
'streetName': [null, [Validators.maxLength(50), PhoneNumberValidator]],
'emailAddress': [null, [Validators.maxLength(50), Validators.email]],
'city': [null, [Validators.required, Validators.maxLength(200)]],
'state': [null, [Validators.maxLength(200)]],
'zip':[null,[Validators.maxLength(200)]]
});
HTML
//嘗試避免用 ngIf 包裹每個項目,根據 UX 線框圖規格,項目被放置在頁面上的特定位置,NgFor 並不完全可行,HTML/CSS 視圖比這複雜得多,
<div class = "row">
<app-input-textbox formControlName = "firstName"></app-input-textbox>
<div class = "row">
<div class = "column">
<app-input-textbox formControlName = "emailAddress"></app-input-textbox>
</div>
<div class = "test">
<app-input-textbox formControlName = "state"></app-input-textbox>
<app-input-textbox formControlName = "zip"></app-input-textbox>
</div>
答案#1
我看到你想要創建一個 "app-input"。我的建議是讓 app-input 注入為構造函數的 FormGroupDirective,並直接使用 [formControl],參見 stackblitz
@Component({
selector: 'app-input',
template: `
<ng-container *ngIf="control && control.enabled">
{{label}}
<input [formControl]="control">
</ng-container>
`
})
export class HelloComponent {
constructor( @Optional() @Host() private form:FormGroupDirective){}
control:FormControl
@Input() set name(value)
{
this.control=this.form?this.form.form.get(value) as FormControl:null
}
@Input() label: string;
}
這使我們有一個像樣的形式
<form [formGroup]="formGroup">
<app-input name="one" label="One"></app-input>
<app-input name="two" label="Two"></app-input>
</form>
如果我們想要添加錯誤,我們可以改進應用程式輸入,使用一個輸入和一個函數來獲取錯誤中的第一個錯誤
@Input() errors:any={} //see that, by defect it's an empty object
getError()
{
for (let key of Object.keys(this.errors))
{
if (this.control.hasError(key))
return this.errors[key]
}
}
並在範本中添加一些像
<div *ngIf="control.touched">
{{getError()}}
</div>
我們的主要應用程式變得像,例如。
<form [formGroup]="formGroup">
<app-input name="one" label="One" [errors]="{required:'One is required'}"></app-input>
<app-input name="two" label="Two"></app-input>
</form>
好吧,這只是一個例子,我希望這對你有幫助
答案#2
為你建立了 stackblitz。
這裡我使用自訂模型(陣列)來渲染欄位:
<h1>My dynamic form</h1>
<form [formGroup]="formGroup">
<div *ngFor="let input of inputList">
<label>{{ input.label }}</label>
<input type="{{ input.type }}" formControlName="{{ input.formControlName }}">
<span (click)="removeInputField(input)">Remove</span>
</div>
<div>
<button type="button" (click)="addInputField()">Add Input Field</button>
<button type="submit">Submit</button>
</div>
</form>
這裡有兩種方法來添加和移除控制項:
addInputField() {
const formControlName = prompt("FormControlName input: ");
const inputType = prompt("Type input: ");
const label = prompt("Label input: ");
const inputData = {
inputType: inputType,
formControlName: formControlName,
label: label
};
this.inputList.push(inputData);
this.formGroup.addControl(
inputData.formControlName,
this.formBuilder.control("")
);
}
removeInputField(inputField: InputField) {
this.formGroup.removeControl(inputField.formControlName);
this.inputList = this.inputList.filter(field => field !== inputField);
}
主要步驟是呼叫 removeControl 和 addControl 方法。
在你的情況下,你只需要呼叫 this.customerForm.removeControl(key)。
