formGroupName 必须与父 formGroup 指令一起使用

Posted

技术标签:

【中文标题】formGroupName 必须与父 formGroup 指令一起使用【英文标题】:formGroupName must be used with a parent formGroup directive 【发布时间】:2020-01-25 09:34:29 【问题描述】:

[编辑]:这就是为什么我在表单标签上使用了 formGroupName 并且它必须在 div 标签上。 formArrayName 还有一个问题,没有错误,但没有出现相关的复选框。 我这样做了,现在它说无法访问未定义的控件..

get operatingRangesFormArray(): FormArray  return this.modifyForm.get('operatingRanges') as FormArray; 

in template : 
        <div ID="divChkBoxTimePicker" formGroupName="checkboxGroupOperatingRange" style="width: 100%;">
            <div style="display:flex; flex-direction: row; align-items: center; justify-content: center;">
                <div class="col-md-6 flex-column-align-start">
                    <div formArrayName="operatingRanges" *ngFor="let item of operatingRangesFormArray.controls; let i = index">
                        <div class="row-no-wrap" *ngIf="i < (operating_ranges.length - 1)/2">
                            <label>
                                <mat-checkbox [value]="operating_ranges[i]?.id" [formControlName]="i" style="margin-right: 5px;" (change)="updateDureeTotaleOperatingRanges($event)">
                                    operating_ranges[i]?.name
                                </mat-checkbox>
                            </label>
                        </div>
                    </div>
                </div>
                <div class="col-md-6 flex-column-align-start">
                    <div formArrayName="operatingRanges" *ngFor="let item of operatingRangesFormArray.controls; let i = index">
                        <div class="row-no-wrap" *ngIf="i > (operating_ranges.length - 1)/2">
                            <label>
                                <mat-checkbox [value]="operating_ranges[i]?.id" [formControlName]="i" style="margin-right: 5px;" (change)="updateDureeTotaleOperatingRanges($event)">
                                    operating_ranges[i]?.name
                                </mat-checkbox>
                            </label>
                        </div>
                    </div>
                </div>
            </div>
            <div *ngIf="!this.modifyForm.get('checkboxGroupOperatingRange').valid">Au moins une gamme opératoire doit être sélectionné</div>
        </div>

我被这个小问题困扰了 2 天:formControlName 必须与父 formGroup 指令一起使用。

我尝试使用响应式表单来更新我的大表单并将其转换为包含多个表单控件和 3 个嵌套表单组的表单组。 结构是:

public equipmentLocationWorkFieldControl: FormControl = new FormControl('');
public equipmentLocationStructureControl: FormControl = new FormControl('');
public equipmentLocationLocalControl: FormControl = new FormControl('');
public equipmentLocationPlaceControl: FormControl = new FormControl('');
public equipmentLocationEquipmentTypeControl: FormControl = new FormControl('');
public equipmentLocationEquipmentControl: FormControl = new FormControl('');
public equipmentNameControl: FormControl = new FormControl('');
public equipmentLocationEquipmentTypeNewControl: FormControl = new FormControl('');
public equipmentLocationEquipmentTypeNew2Control: FormControl = new FormControl('');
public equipmentSurnameControl: FormControl = new FormControl('');
public equipmentSerialControl: FormControl = new FormControl('');
public equipmentLocationBrandControl: FormControl = new FormControl('');
public equipmentLocationModelControl: FormControl = new FormControl('');
public equipmentLocationWorkFieldNewControl: FormControl = new FormControl('');
public equipmentLocationEquipmentSelectedControl: FormControl = new FormControl('');
public equipmentSelectedControl: FormControl = new FormControl('');
public equipmentSelectedIdControl: FormControl = new FormControl('');
public operatingRanges: FormArray = new FormArray([], this.minSelectedCheckboxes(1));
public agentsDispo: FormArray = new FormArray([], this.minSelectedCheckboxes(1));
public agentsInShiftSelected: FormArray = new FormArray([], this.minSelectedCheckboxes(1));
public checkboxGroupAgentInShiftAndDispoAndIntervenant: FormGroup = new FormGroup(
    shiftControl: this.shiftControl,
    agentsInShiftSelected: this.agentsInShiftSelected,
    agentsDispo: this.agentsDispo,
    agentParticipantsControl: this.agentParticipantsControl,
    externalActorControl: this.externalActorControl,
    externalActorParticipantsControl: this.externalActorParticipantsControl,
);
public checkboxGroupOperatingRange: FormGroup = new FormGroup(
    operatingRanges: this.operatingRanges,
);



(IN NG_INIT FUNCTION)
this.modifyForm = this.formBuilder.group(
        dateDeb: this.dateDeb,
        dateFin: this.dateFin,
        workTypeControl: this.workTypeControl,
        description: this.description,
        note: this.note,
        checkboxGroupOperatingRange: this.formBuilder.group(
            operatingRanges: this.operatingRanges,
        ),
        checkboxGroupAgentInShiftAndDispoAndIntervenant: this.formBuilder.group(
            shiftControl: this.shiftControl,
            agentsInShiftSelected: this.agentsInShiftSelected,
            agentsDispo: this.agentsDispo,
            agentParticipantsControl: this.agentParticipantsControl,
            externalActorControl: this.externalActorControl,
            externalActorParticipantsControl: this.externalActorParticipantsControl,
        ),
        equipmentLocationForm: this.formBuilder.group( 
            equipmentLocationWorkFieldControl: this.equipmentLocationWorkFieldControl,
            equipmentLocationStructureControl: this.equipmentLocationStructureControl,
            equipmentLocationLocalControl: this.equipmentLocationLocalControl,
            equipmentLocationPlaceControl: this.equipmentLocationPlaceControl,
            equipmentLocationEquipmentTypeControl: this.equipmentLocationEquipmentTypeControl,
            equipmentLocationEquipmentControl: this.equipmentLocationEquipmentControl,
            equipmentNameControl: this.equipmentNameControl,
            equipmentLocationEquipmentTypeNewControl: this.equipmentLocationEquipmentTypeNewControl,
            equipmentLocationEquipmentTypeNew2Control: this.equipmentLocationEquipmentTypeNew2Control,
            equipmentSurnameControl: this.equipmentSurnameControl,
            equipmentSerialControl: this.equipmentSerialControl,
            equipmentLocationBrandControl: this.equipmentLocationBrandControl,
            equipmentLocationModelControl: this.equipmentLocationModelControl,
            equipmentLocationWorkFieldNewControl: this.equipmentLocationWorkFieldNewControl,
            equipmentLocationEquipmentSelectedControl: this.equipmentLocationEquipmentSelectedControl,
            equipmentSelectedControl: this.equipmentSelectedControl,
            equipmentSelectedIdControl: this.equipmentSelectedIdControl,
            equipmentControl: this.equipmentControl,
        )
    );

第二个问题是找不到名称为“equipmentControl”的控件,并且无法读取关于这些行的未定义属性“push”:

 const control = new FormControl(false); // if first item set to true, else false
 (this.checkboxGroupAgentInShiftAndDispoAndIntervenant.controls.agents_dispo as FormArray).push(control);

模板结构最少但不是最后一个:

<form *ngIf="modifyForm" [formGroup]="modifyForm" (ngSubmit)="modifyIntervention()">
    <input matInput [matDatepicker]="picker" required placeholder="Choisir la date d'intervention" formControlName="dateDeb" (dateChange)="updateDate()">
    <input matInput [matDatepicker]="picker1" required placeholder="Choisir la date de cloture" [value]="dateDeb.value" formControlName="dateFin">
    <mat-select formControlName="workTypeControl" required [(value)]="selectedWorkTypeForMaincouranteModify">
                        <mat-option [value]="0">Choisir une type de travail</mat-option>
                        <mat-option *ngFor="let item of work_types" [value]="item.id"> item.name </mat-option>
                    </mat-select>
    <textarea matInput placeholder="Description" formControlName="description" required></textarea>
    <textarea matInput placeholder="Remarque" formControlName="note"></textarea>
    <form formGroupName="checkboxGroupOperatingRange" style="width: 100%;">
        <div class="col-md-6 flex-column-align-start">
            <div formArrayName="operatingRanges" *ngFor="let item of operatingRanges.controls; let i = index">
                <div class="row-no-wrap" *ngIf="i < (operating_ranges.length - 1)/2">
                    <label>
                        <mat-checkbox [value]="operating_ranges[i]?.id" [formControlName]="i" style="margin-right: 5px;" (change)="updateDureeTotaleOperatingRanges($event)">
                                                operating_ranges[i]?.name
                        </mat-checkbox>
                    </label>
                </div>
             </div>
         </div>
         <div class="col-md-6 flex-column-align-start">
             <div formArrayName="operatingRanges" *ngFor="let item of this.modifyForm['controls'].checkboxGroupOperatingRange['controls'].operatingRanges.value; let i = index">
                 <div class="row-no-wrap" *ngIf="i > (operating_ranges.length - 1)/2">
                     <label>
                         <mat-checkbox [value]="operating_ranges[i]?.id" [formControlName]="i" style="margin-right: 5px;" (change)="updateDureeTotaleOperatingRanges($event)">
                                                operating_ranges[i]?.name
                         </mat-checkbox>
                     </label>
                  </div>
              </div>
          </div>
    </form>
    <form formGroupName="checkboxGroupAgentInShiftAndDispoAndIntervenant" style="width: 100%;">
        <div class="divHiddenUnderButton" *ngIf="isOpenSaisieParticipant">
            <mat-form-field style="display: inline !important;width: 100%;">
                <mat-select formControlName="shiftControl" required [(value)]="selectedShiftForMaincouranteModify" (selectionChange)="getAgentsInShiftAndDispo()">
                    <mat-option [value]="0">Choisir la vacation</mat-option>
                    <mat-option *ngFor="let item of shifts" [value]="item.id"> item.name </mat-option>
                </mat-select>
            </mat-form-field>
            <div ID="AgentVacation" style="display: inline !important;width: 100%;">
                <div class="col-md-6 flex-column-align-start">
                    <div formArrayName="agentsInShiftSelected" *ngFor="let item of checkboxGroupAgentInShiftAndDispoAndIntervenant.controls.agentsInShiftSelected.controls; let i = index">
                        <label *ngIf="i < (agentsInShiftSelected.length-1)/2">
                        <mat-checkbox [value]="agentsInShiftSelected[i]?.id" [formControlName]="i" style="margin-right: 5px;" >
                                                agentsInShiftSelected[i]?.firstname.charAt(0).agentsInShiftSelected[i]?.lastname
                        </mat-checkbox>
                        </label>
                    </div>
                </div>
                <div class="col-md-6 flex-column-align-start">
                    <div formArrayName="agentsInShiftSelected" *ngFor="let item of checkboxGroupAgentInShiftAndDispoAndIntervenant.controls.agentsInShiftSelected.controls; let i = index">
                        <label *ngIf="i > (agentsInShiftSelected.length-1)/2">
                        <mat-checkbox [value]="agentsInShiftSelected[i]?.id" [formControlName]="i" style="margin-right: 5px;" >
                                                agentsInShiftSelected[i]?.firstname.charAt(0).agentsInShiftSelected[i]?.lastname
                        </mat-checkbox>
                        </label>
                    </div>
                </div>
            </div>                
        </div>
        <div class="flex-column-center" style="margin-top:10px;" *ngIf="selectedShiftForMaincouranteModify !== 0 && isOpenSaisieVacation">
            <div style="display:flex; flex-direction: row; align-items: center; justify-content: center;">
                <div formArrayName="agentsDispo" *ngFor="let item of checkboxGroupAgentInShiftAndDispoAndIntervenant.controls.agentsDispo.controls; let i = index">
                    <label *ngIf="i < (agentsDispo.length-1)/2">
                    <mat-checkbox [value]="agentsDispo[i]?.id" [formControlName]="i" style="margin-right: 5px;" >
                                                    agentsDispo[i]?.firstname.charAt(0).agentsDispo[i]?.lastname
                    </mat-checkbox>
                    </label>
                </div>
                <div formArrayName="agentsDispo" *ngFor="let item of checkboxGroupAgentInShiftAndDispoAndIntervenant.controls.agentsDispo.controls; let i = index">
                    <label *ngIf="i > (agentsDispo.length-1)/2">
                    <mat-checkbox [value]="agentsDispo[i]?.id" [formControlName]="i" style="margin-right: 5px;" >
                                                    agentsDispo[i]?.firstname.charAt(0).agentsDispo[i]?.lastname
                    </mat-checkbox>
                    </label>
                </div>
            </div>
        </div>
        <mat-select formControlName="agentParticipantsControl" required [(value)]="selectedAgentParticipantsForMaincouranteModify">
            <mat-option *ngFor="let item of participants" [value]="item.id">item.firstname.charAt(0). item.lastname </mat-option>
         </mat-select>
         <mat-select formControlName="externalActorControl" [(value)]="selectedExternalActorForMaincouranteModify">
             <mat-option [value]="0">Choisir un intervenant externe</mat-option>
             <mat-option *ngFor="let item of external_actors" [value]="item.id">item.name</mat-option>
         </mat-select>
         <mat-select formControlName="externalActorParticipantsControl" [(value)]="selectedExternalActorParticipantsForMaincouranteModify">
             <mat-option *ngFor="let item of external_actor_participants" [value]="item.id">item.name</mat-option>
         </mat-select>
     </form>
     <form formGroupName="equipmentLocationForm">
         <input formControlName = "equipmentLocationStructureControl">
         <input formControlName = "equipmentLocationPlaceControl">
         <input formControlName = "equipmentLocationWorkFieldControl">
         <input formControlName = "equipmentLocationEquipmentTypeControl">
         <input formControlName = "equipmentLocationEquipmentControl">
         ..........
     </form>
     <mat-select formControlName="equipmentControl" required [(value)]="selectedEquipmentForMaincouranteModify" (selectionChange)="updateOtherFields($event)">
         <mat-option *ngFor="let item of equipments_participants" [value]="item.id">
                        item.name(item.equipment_locations[0].structure.name[item.equipment_locations[0].structure_id]|
                        item.equipment_locations[0].local.name[item.equipment_locations[0].local_id]|
                        item.equipment_locations[0].place.name[item.equipment_locations[0].place_id])
         </mat-option>
     </mat-select>
</form>

当我编写结构时,我注意到我的表单组父 modifyForm 包含所有其他表单。 modifyForm 的表单结束标记包含所有其他子表单。所以决定去掉 modifyForm 的结束标签,把它放在下一个 formGroupName 之前,比结构是:

<form [formGroup] = "">
        <input formControlName = "">
        ....
    <form formGroupName = "">
        <input formControlName = "">
        ....
    </form>
    <form formGroupName = "">
        <input formControlName = "">
        ....
        <div formArrayName="operatingRanges" *ngFor="let item of operatingRanges.controls; let i = index">
            <label>
            <mat-checkbox [value]="operating_ranges[i]?.id" [formControlName]="i" style="margin-right: 5px;" (change)="updateDureeTotaleOperatingRanges($event)">
                                            operating_ranges[i]?.name
            </mat-checkbox>
            </label>
        </div>
    </form>
    <form formGroupName = "">
        <input formControlName = "">
        ....
    </form>
</form>

现在,结构如下。然后错误是 。 AND formControlName 必须与父 formGroup 指令一起使用。

    <form [formGroup] = "">
        <input formControlName = "">
        ....
    </form>
    <form formGroupName = "">
        <input formControlName = "">
        ....
    </form>
    <form formGroupName = "">
        <input formControlName = "">
        ....
        <div formArrayName="operatingRanges" *ngFor="let item of operatingRanges.controls; let i = index">
            <label>
            <mat-checkbox [value]="operating_ranges[i]?.id" [formControlName]="i" style="margin-right: 5px;" (change)="updateDureeTotaleOperatingRanges($event)">
                                            operating_ranges[i]?.name
            </mat-checkbox>
            </label>
        </div>
    </form>
    <form formGroupName = "">
        <input formControlName = "">
        ....
    </form>

请有人帮忙找出为什么它不能识别我的表单控件字段?我做错了什么?我按照文档...

【问题讨论】:

请将完整的错误堆栈发布为文本,以及minimal reproducible example。 为什么要创建数百个 FormControl 只是为了将它们放在一个组中。请查看 FormBuilder 的 文档;你在做的事情不太对 Guillaume,formGroup 必须在 div &lt;div formGroupName="checkboxGroupOperatingRange" &gt;...&lt;/div&gt; 不在
..**WRONG**..
哦,对于最后的 cmets,我将尝试使用它。为什么我声明所有 formcontrol 并重新设置是因为如果我不这样做,它将引发有关未定义的 formcontrol name xxxxx 的错误 另外,小心点。当您使用 ReactiveForms 时,不要使用 [value](或更改),如果您有一个 fromControl(您有 formConhtrolName),则此获取/更新该值。注意:我作为“响应”添加了如何使用 FomrArray 和 FormGroup 的构造函数创建表单(您也可以使用 FormBuilder 创建) 【参考方案1】:

由于声誉低,无法发表评论,所以我在这里发表评论。

在我看来,问题的出现是因为您试图在 FormGroup 中使用 FormArray

    <form [formGroup] = "">
        <input formControlName = "">
        ....
    </form>
    <form formGroupName = "">
        <input formControlName = "">
        ....
    </form>
------------- Fix this part --------------
    <form formGroupName = "">
        <input formControlName = "">
        ....
        <div formArrayName="operatingRanges" *ngFor="let item of operatingRanges.controls; let i = index">
            <label>
            <mat-checkbox [value]="operating_ranges[i]?.id" [formControlName]="i" style="margin-right: 5px;" (change)="updateDureeTotaleOperatingRanges($event)">
                                            operating_ranges[i]?.name
            </mat-checkbox>
            </label>
        </div>
    </form>
---------------------------------------------
    <form formGroupName = "">
        <input formControlName = "">
        ....
    </form>

【讨论】:

请解释一下这样做是什么?认为在文档中是这样的:s 每个表单元素都必须在表单组中,不是吗?即使我把 formArrayName 放在哪里? 我在文档中找到了这个,他们将 formArrayName 放在 formGroup 中。 angular.io/api/forms/FormArrayName#description【参考方案2】:

注意:您可以像这样创建表单

this.modiyForm=new FormGroup(
  dateDeb:new FormControl(),
  dateFin:new FormControl(),
  workTypeControl:new FormControl(),
  description:new FormControl(),
  Remarque:new FormControl(),
  checkboxGroupOperatingRange:new FormGroup(
      operatingRanges:new FormArray([])
  )
  checkboxGroupAgentInShiftAndDispoAndIntervenant:new FormGroup(
      shiftControl:new FormControl()
      agentsInShiftSelected:new FormArray([]),
      agentsDispo:new FormArray([]),
      agentParticipantsControl:new FormControl(),
      externalActorControl:new FormControl(),
      externalActorParticipantsControl:new FormControl(),
  ),
  equipmentLocationForm:new FormGroup(
     equipmentLocationStructureControl:new FormControl()
     equipmentLocationPlaceControl:new FormControl()
     ...
  )

)

【讨论】:

是的,我可以,它可以通过这种方式完成(传统的使用 FormGroup、FormControl 等。其他方式使用 formbuilder,但它是一样的。

以上是关于formGroupName 必须与父 formGroup 指令一起使用的主要内容,如果未能解决你的问题,请参考以下文章

需要一些关于 [formGroup] formGroupName ,[formControl] formControlName 的建议

ERROR 错误:formArrayName 必须与父 formGroup 指令一起使用

formControlName 必须与父 formGroup 指令一起使用

错误:formControlName 必须与父 formGroup 指令一起使用。您需要添加一个 formGroup 指令 - Angular 反应式表单

子类构造器与父类构造器

java的重写