如何使用formControlName并处理嵌套的formGroup?

问题描述 投票:0回答:5
forms angular angular-reactive-forms
5个回答
151
投票

您可以使用表单组,它基本上是一个控件集合(控件是指 html 表单中给出的字段),在您的打字稿语法中定义并使用 formControlName 指令绑定到您的 HTML 元素,例如

this.myForm = fb.group({
    'fullname': ['', Validators.required],
    'gender': [],
    'address': fb.group({
        'street': [''],
        'houseNumber': [''],
        'postalCode': ['']
    })
});

模板:

<form [formGroup]="myForm" >
   <div class="form-group">
      <label for="fullname">Username</label>
      <input type="text" id="username" formControlName="fullname" class="form-control">            
   </div>
   <div class="radio" *ngFor="let gender of genders">
      <label>
      <input type="radio" formControlName="gender" [value]="gender">{{ gender }} </label>
   </div>
   <div formGroupName="address">
      <div class="form-group">
         <label for="street">Username</label>
         <input type="text" id="username" value="street" formControlName="street" class="form-control">            
      </div>
      <div class="form-group">
         <label for="houseNumber">Username</label>
         <input type="text" id="username" value="street" formControlName="houseNumber" class="form-control">            
      </div>
      <div class="form-group">
         <label for="postalCode">Username</label>
         <input type="text" id="username" value="street" formControlName="postalCode" class="form-control">            
      </div>
   </div>
</form>

一个 formGroup 可以由一个嵌套的 formGroup 组成,并且层次结构可以继续,但是在访问值时它相当简单。


25
投票

确实如此。查看formGroupName

this.myForm = fb.group({
    'fullname': ['', Validators.required],
    'gender': [],
    'address': fb.group({
        'street': [''],
        'houseNumber': [''],
        'postalCode': ['']
    })
});

<form [formGroup]="myForm" >
   <div class="form-group">
      <label for="fullname">Username</label>
      <input type="text" id="username" formControlName="fullname" class="form-control">            
   </div>
   <div class="radio" *ngFor="let gender of genders">
      <label>
      <input type="radio" formControlName="gender" [value]="gender">{{ gender }} </label>
   </div>
   <div formGroupName="address">
      <div class="form-group">
         <label for="street">Username</label>
         <input type="text" id="username" value="street" formControlName="street" class="form-control">            
      </div>
      <div class="form-group">
         <label for="houseNumber">Username</label>
         <input type="text" id="username" value="street" formControlName="houseNumber" class="form-control">            
      </div>
      <div class="form-group">
         <label for="postalCode">Username</label>
         <input type="text" id="username" value="street" formControlName="postalCode" class="form-control">            
      </div>
   </div>
</form>

15
投票

tl;博士:

您可以将表单分解为使用嵌套 formgroups 的组件,并且 formcontrolname 可以正常使用。

我倾向于使用的方法是,由于嵌套表单组通常用于指定表单的单独部分,因此我倾向于将其分解为组件并将这些组件传递给嵌套表单组作为输入参数。 因此,在您的情况下,我将有一个 address 组件,它采用表单组作为参数:

<app-address [formGroup]="myForm.get('address')"></app-address

在该组件内部,我只会有一个将在 html 中使用的 @Input() formGroup:

<div [formGroup]="formGroup">
....

这样您就可以像平常一样显式引用控件名称,因为它将成为此表单组的一部分。

此外,请记住该表格是作为参考传递的。您的更改将在父组件的 myForm 元素中进行说明,如果您需要访问不在您的 formgroup 中的表单部分(验证、更改检测等),您始终可以传递整个表单并只需将 formgroup 定义为明确引用内部组:

<div [formGroup]="formGroup.get('adress')">

(假设您传递了整个表单对象

编码愉快!


0
投票

我正在努力解决 Angular 10 中的一个问题。 我有一个“parent”form group“forma”,它有几个依赖组:“company”,同时“company”有两个 “孩子”与其他组,msgAccountssocialMedia。 当我填写表单并提交时,在后端一切都是正确的,我可以看到这些数据如何存储在数据库中 正确,但是当我收到这个 json 时,我无法显示数据 控件中的“company.msgAccounts”和“company.socialMedia”内 (输入)。这是我从服务器得到的:

            {
            name:'',
            active: '',
            ........
            company:{
              msgAccounts:{line: "@linedemo", whatsapp: "0325554244"},
              socialMedia: {fb: '', tw: '', is: ''}
             }   
            ..........
            }
    
 this.forma = this.fb.group( {
          siteName  : [ '', [Validators.required, Validators.minLength(5)]],
          siteEmail  : [ '', [Validators.required, Validators.minLength(5)]],
          // defaultLocation: [ '', [Validators.required, Validators.minLength(10)]],
          active  : [ true, [Validators.required, Validators.minLength(5)]],
          mainLanguage: ['' , [Validators.required, Validators.minLength(2)]],
        
          company: this.fb.group({
            name: [''],
            address: [''],
            phone: [''],
            msgAccounts: this.fb.group({
              line: [],
              whatsapp: []
            }),
            socialMedia: this.fb.group({
              fb: [],
              is: [],
              tw: []
            })
          })
        });
    
    And the html: (Sorry about the indentation, when it was not easy using this editor, and I just pasted a part of the code in order to do it as shorter as possible).
    
            <mat-tab-group>   
                    <mat-tab label="settings">
                        <form autocomplete="off" >
                            <ng-template ng-template matTabContent> 
                                <mat-tab-group  [formGroup]="forma">
                                        <mat-tab label="global"> 
                                           // All this fields have are fine
                                         </mat-tab>
    
                                 <mat-tab formGroupName="company" label="company"> 
                                    <div class="card">
                                        <div class="card-header" id="headingTwo">
                                            <h5 class="mb-0">Details</h5>
                                        </div>
                                        <div id="company-details">
                                                <div class="form-group row">
                                                    <div class="col-sm-3">
                                                        <input 
                                                        type="text" 
                                                        class="form-control" 
                                                        id="name" 
                                                        name="name"
                                                        placeholder="Company name"
                                                        formControlName=name>
                                                    </div>
                        
                                                </div>
    
                             <div class="form-group row" formGroupName="msgAccounts">
                                                    <div class="col-sm-6">
                                             
                                                        <input 
                                                        type="text" 
                                                        class="form-control" 
                                                        id="line" 
                                                        name="line"
                                                        placeholder="line"
                                                        formControlName=line>
                                                    </div>
                                                    <div class="col-sm-6">
                                                    
                                                        <input 
                                                        type="text" 
                                                        class="form-control" 
                                                        id="whatsapp" 
                                                        name="whatsapp"
                                                        placeholder="whatsapp"
                                                        formControlName=whatsapp>
                                                    </div>
                                                </div>
    
                                                    
    
                             <div class="form-group row" formGroupName="socialMedia" >
                         
                                                    <div class="col-sm-6">
                                                        <input 
                                                        type="text" 
                                                        class="form-control" 
                                                        id="is" 
                                                        name="is"
                                                        placeholder="Is"
                                                        formControlName=is>
                                                    </div>
                                                </div>                             
                                            </div>
                                       </div>
                                </mat-tab>                 
               </mat-tab-group>  
                            <div class="form-group row">
                            <div class="col-sm-10">
                               <button type="submit" 
                                   (click)="saveConfig()">Save</button>
                            </div>
            </div>
                        
           </ng-template>
          </form>
       </mat-tab>
    </mat-tab-group>  

0
投票

在搜索类似的东西时,但如果需要构建

FormGroup
动态,您可以执行以下操作:

打字稿

// ... 
export class MyComponent implements OnInit { 
    public myForm: FormGroup = new FormGroup({
        fullName: new FormControl('', Validators.required),
        gender: new FormControl(),
    });
    
    public constructor(
        private fb: FormBuilder,
    ) {
        // ...  
    }
    
    public ngOnInit(): void {   
        const addressGrp = this.fb.group({}); // OR new FormGroup({})
        this.myForm.addControl('address', addressGrp); // adding address to group ahead
        
        const fieldsToAppend = ['street', 'houseNumber', 'postalCode']; // this can come from API response too
                
        fieldsToAppend.forEach(propName =>
            addressGrp.addControl(propName, this.fb.control(''))); // it can be also:
                                                                   // 1. new FormControl()
                                                                   // 2. this.fb.control('', Validators.required))) 
                                                                   // 3. new FormControl('', Validators.required)

        // this.myForm.get('address').value  === {street: '', houseNumber: '', postalCode: ''}
    }
}

HTML

<form [formGroup]="myForm" >
    ... 
    <div formGroupName="address">
        ...
        <input class="form-control" formControlName="street" />
        ...
        <input class="form-control" formControlName="houseNumber" />
        ...
        <input class="form-control" formControlName="postalCode" />
    </div>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.