1

我想從樹結構生成反應形式。角度4嵌套組的動態形式

這是創建表單項(表單組和控件)的代碼。對於嵌套在表單組中的控件,我使用遞歸模板。

import { Component, Input, NgModule } from '@angular/core'; 
 
import { BrowserModule } from '@angular/platform-browser'; 
 
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; 
 

 
@Component({ 
 
    selector: 'form-item', 
 
    template: ` 
 
    <ng-container [formGroup]="form"> 
 
     <ng-container *ngTemplateOutlet="formItemTemplate; context:{ $implicit: pathSegments }"></ng-container> 
 

 
     <ng-template #formItemTemplate let-pathSegments> 
 
     
 
     <ng-container *ngIf="pathSegments.length > 1"> 
 
      <div [formGroupName]="pathSegments[0]" class="form-group"> 
 
      <ng-container *ngTemplateOutlet="formItemTemplate; context:{ $implicit: pathSegments.slice(1) }"></ng-container> 
 
      </div> 
 
     </ng-container> 
 

 
     <ng-container *ngIf="pathSegments.length === 1"> 
 
      <div class="form-control"> 
 
      <label>{{pathSegments[pathSegments.length - 1]}}</label> 
 
      <!--<input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/>--> 
 
      <input type="text"/> 
 
      </div> 
 
     </ng-container> 
 
     
 
     </ng-template> 
 
    </ng-container> 
 
    `, 
 
}) 
 
export class AppControlComponent { 
 

 
    @Input() form: FormGroup; 
 

 
    @Input() 
 
    set path(path: string) { 
 
    this.pathSegments = path.split('.'); 
 
    } 
 
    pathSegments: string[] = []; 
 

 
    constructor() { } 
 
} 
 

 

 
@Component({ 
 
    selector: 'app-root', 
 
    template: ` 
 
    <form [formGroup]="questionForm"> 
 
     <h1>Question Form</h1> 
 

 
     <form-item [form]="questionForm" path="question"></form-item> 
 
     <form-item [form]="questionForm" path="answers.answer1"></form-item> 
 
     <form-item [form]="questionForm" path="answers.answer2"></form-item> 
 
     <form-item [form]="questionForm" path="answers.answer3"></form-item> 
 

 
     <button type="submit">submit</button> 
 

 
     <pre>{{questionForm.value | json}}</pre> 
 
    </form> 
 
    `, 
 
}) 
 
export class AppComponent { 
 
    private questionForm: FormGroup; 
 

 
    constructor(private fb: FormBuilder) { 
 
    this.questionForm = this.fb.group({ 
 
     question: ['', Validators.required], 
 
     answers: this.fb.group({ 
 
     answer1: ['', Validators.required], 
 
     answer2: ['', Validators.required], 
 
     answer3: ['', Validators.required], 
 
     }), 
 
    }); 
 
    } 
 
} 
 

 
@NgModule({ 
 
    imports: [BrowserModule, FormsModule, ReactiveFormsModule], 
 
    declarations: [ 
 
    AppComponent, 
 
    AppControlComponent 
 
    ], 
 
    bootstrap: [AppComponent] 
 
}) 
 
export class AppModule {}

形式HTML是完全生成。但是,當我將formControlName指令添加到輸入時,HTML生成會中斷。然後,我得到這樣的錯誤:

Error: Cannot find control with name: 'answer1' 
+0

什麼錯誤你好嗎? – yurzui

+0

'FormControlName'指令使用'@Optional()@Host()@SkipSelf()parent:ControlContainer'查找父窗體' – yurzui

+0

錯誤:無法找到名稱爲'answer1'的控件 –

回答

1

要支持嵌套組的無限數量的我會用標記,如:

<ng-container [formGroup]="form"> 
    <ng-container 
    *ngTemplateOutlet="formItemTemplate; context:{ $implicit: 0, group: form }"> 
    </ng-container> 

    <ng-template #formItemTemplate let-i let-group="group"> 
     <fieldset *ngIf="i < pathSegments.length - 1" class="form-group"> 
     <legend>{{ pathSegments[i] }}</legend> 
     <ng-container 
      *ngTemplateOutlet="formItemTemplate; 
      context:{ $implicit: i + 1, group: group.get(pathSegments[i]) }"> 
     </ng-container> 
     </fieldset> 

     <div *ngIf="i + 1 === pathSegments.length" class="form-control" [formGroup]="group"> 
     <label>{{pathSegments[pathSegments.length - 1]}}</label> 
     <input [formControlName]="pathSegments[pathSegments.length - 1]"/> 
     </div> 
    </ng-template> 
</ng-container> 

Plunker Example

0

由於@yurzui在評論中提及,因爲FormControlName指令使用 @Optional() @Host() @SkipSelf() parent: ControlContainer 找到父formGroup出現問題。

因此,下面的代碼工作正常,但包含代碼重複並支持有限數量的嵌套組。

@Component({ 
 
    selector: 'form-item', 
 
    template: ` 
 
    <ng-container [formGroup]="form"> 
 

 
     <div class="form-control" *ngIf="pathSegments.length === 1"> 
 
     <label>{{pathSegments[pathSegments.length - 1]}}</label> 
 
     <input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/> 
 
     </div> 
 

 
     <ng-container *ngIf="pathSegments.length === 2" [formGroupName]="pathSegments[0]"> 
 
     <div class="form-control"> 
 
      <label>{{pathSegments[pathSegments.length - 1]}}</label> 
 
      <input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/> 
 
     </div> 
 
     </ng-container> 
 

 
     <ng-container *ngIf="pathSegments.length === 3" [formGroupName]="pathSegments[0]"> 
 
     <ng-container [formGroupName]="pathSegments[1]"> 
 
      <div class="form-control"> 
 
      <label>{{pathSegments[pathSegments.length - 1]}}</label> 
 
      <input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/> 
 
      </div> 
 
     </ng-container> 
 
     </ng-container> 
 

 
     <ng-container *ngIf="pathSegments.length === 4" [formGroupName]="pathSegments[0]"> 
 
     <ng-container [formGroupName]="pathSegments[1]"> 
 
      <ng-container [formGroupName]="pathSegments[2]"> 
 
      <div class="form-control"> 
 
       <label>{{pathSegments[pathSegments.length - 1]}}</label> 
 
       <input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/> 
 
      </div> 
 
      </ng-container> 
 
     </ng-container> 
 
     </ng-container> 
 
    </ng-container> 
 
    `, 
 
})

任何想法如何提高呢?