代码之家  ›  专栏  ›  技术社区  ›  brk

如何使用valueChanges从角度中动态添加的嵌套形式中获取值?

  •  2
  • brk  · 技术社区  · 6 月前

    我正在动态添加 formControl 通过迭代对象数组和;希望通过添加 valueChanges 到父窗体内部 ngOnInit 方法

    在我的代码中 value更改 只能跟踪表单中已经存在的输入的变化,而不能跟踪动态添加的元素的变化。

    这是我的代码

    import 'zone.js';
    import {
      Component,
      inject,
      OnInit,
      signal,
      WritableSignal,
    } from '@angular/core';
    import {
      bootstrapApplication
    } from '@angular/platform-browser';
    import {
      FormBuilder,
      FormsModule,
      ReactiveFormsModule,
      FormControl,
    } from '@angular/forms';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [ReactiveFormsModule, FormsModule],
      template: `
        <form [formGroup] = 'employeeForm'>
         <input formControlName='orgName'>
         @if(showEmpInfo().length > 0){
          <div formGroupName="dynamicContent">
            @for(emp of showEmpInfo();track emp){
               <input type = 'text' 
                [formControlName] = "emp.formControlName">
    
            }
    
          </div>
         }
        <button (click) ='addControl()'>Add</button>
    
        </form>
      `,
    })
    export class App implements OnInit {
      fb = inject(FormBuilder);
      showEmpInfo: WritableSignal < any[] > = signal([]);
      employeeForm = this.fb.group({
        orgName: [''],
        dynamicContent: this.fb.group({}),
      });
    
      formObj = [{
          type: 'text',
          formControlName: 'employee',
        },
    
        {
          type: 'text',
          formControlName: 'empId',
        },
      ];
    
      ngOnInit() {
        this.employeeForm.valueChanges.subscribe((val) => console.log(val));
      }
    
      addControl() {
        const dynamicForm = this.fb.group({});
        this.formObj.forEach((elem) => {
          dynamicForm.addControl(elem.formControlName, new FormControl('', []));
        });
        this.employeeForm.controls['dynamicContent'] = dynamicForm;
        this.showEmpInfo.set(this.formObj);
      }
    }
    
    bootstrapApplication(App);
    

    但如果我加上 value更改 dynamicForm 控制类 this.dynamicForm.valueChanges 动态添加内容后,可以跟踪动态内容的变化。

    我的问题是,我如何避免添加 this.dynamicsForm.value更改 迭代后仅通过添加来跟踪动态控制中的变化 value更改 到根formGroup,这是在 ngOnit ?

    你可以看到 console.log 在键入动态添加的控件时不记录日志,但仅在键入静态窗体控件时记录日志

    这是 Stackblitz Demo Link

    1 回复  |  直到 6 月前
        1
  •  2
  •   Naren Murali    6 月前

    作为另一种解决方案,我建议使用表单数组,在处理循环时,请查看此示例以供参考。

    import 'zone.js';
    import {
      Component,
      inject,
      OnInit,
      signal,
      WritableSignal,
    } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import {
      FormBuilder,
      FormsModule,
      ReactiveFormsModule,
      FormControl,
      FormArray,
      FormGroup,
    } from '@angular/forms';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [ReactiveFormsModule, FormsModule],
      template: `
        <form [formGroup] = 'employeeForm'>
         <input formControlName='orgName'>
        <div formArrayName="dynamicContent">
          @for(group of formArrayControls();track group; let i = $index){
            <div [formGroupName]="i">
              @for(controlObj of formObj;track controlObj){
                <input [formControlName]="controlObj.formControlName" 
                [type]="controlObj.type"/>
              }
            </div>
          }
        </div>
        <button (click) ='addControl()'>Add</button>
    
        </form>
      `,
    })
    export class App implements OnInit {
      fb = inject(FormBuilder);
      showEmpInfo: WritableSignal<any[]> = signal([]);
      employeeForm = this.fb.group({
        orgName: [''],
        dynamicContent: this.fb.array([]),
      });
    
      formObj = [
        {
          type: 'text',
          formControlName: 'employee',
        },
    
        {
          type: 'text',
          formControlName: 'empId',
        },
      ];
    
      ngOnInit() {
        this.employeeForm.valueChanges.subscribe((val) => console.log(val));
      }
    
      formArrayControls() {
        return (this.employeeForm!.get('dynamicContent') as FormArray)!
          .controls as FormGroup[];
      }
    
      addControl() {
        const dynamicForm = this.employeeForm.controls[
          'dynamicContent'
        ] as FormArray;
        const formGroup = this.fb.group({});
        this.formObj.forEach((elem) => {
          formGroup.addControl(elem.formControlName, new FormControl('', []));
        });
        dynamicForm.push(formGroup);
        this.showEmpInfo.update((prev) => {
          prev.push(this.formObj);
          return prev;
        });
      }
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo


    您添加的控件不正确,必须使用以下方法添加控件 addControl 。我们引用动态内容并将其分配给 dynamicForm ,然后当我们循环遍历数组时,我们使用add控件直接添加控件。

    addControl() {
        const dynamicForm = this.employeeForm.controls['dynamicContent'];
        this.formObj.forEach((elem) => {
          dynamicForm.addControl(elem.formControlName, new FormControl('', []));
        });
        this.showEmpInfo.set(this.formObj);
      }
    

    完整代码:

    import 'zone.js';
    import {
      Component,
      inject,
      OnInit,
      signal,
      WritableSignal,
    } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import {
      FormBuilder,
      FormsModule,
      ReactiveFormsModule,
      FormControl,
    } from '@angular/forms';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [ReactiveFormsModule, FormsModule],
      template: `
        <form [formGroup] = 'employeeForm'>
         <input formControlName='orgName'>
         @if(showEmpInfo().length > 0){
          <div formGroupName="dynamicContent">
            @for(emp of showEmpInfo();track emp){
               <input type = 'text' 
                [formControlName] = "emp.formControlName">
    
            }
    
          </div>
         }
        <button (click) ='addControl()'>Add</button>
    
        </form>
      `,
    })
    export class App implements OnInit {
      fb = inject(FormBuilder);
      showEmpInfo: WritableSignal<any[]> = signal([]);
      employeeForm = this.fb.group({
        orgName: [''],
        dynamicContent: this.fb.group({}),
      });
    
      formObj = [
        {
          type: 'text',
          formControlName: 'employee',
        },
    
        {
          type: 'text',
          formControlName: 'empId',
        },
      ];
    
      ngOnInit() {
        this.employeeForm.valueChanges.subscribe((val) => console.log(val));
      }
    
      addControl() {
        const dynamicForm = this.employeeForm.controls['dynamicContent'];
        this.formObj.forEach((elem) => {
          dynamicForm.addControl(elem.formControlName, new FormControl('', []));
        });
        this.showEmpInfo.set(this.formObj);
      }
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo