【问题标题】:Angular 2 - Can't set form array valueAngular 2 - 无法设置表单数组值
【发布时间】:2017-08-04 19:34:37
【问题描述】:

我收到此错误:

还没有向该数组注册的表单控件。如果您使用的是 ngModel,您可能需要检查下一个刻度(例如,使用 setTimeout)。

使用此代码时:

public settingsForm: FormGroup = this.fb.group({
  collaborators: this.fb.array([]),
  rsvp: this.fb.group({
    latestDate: ['', [Validators.required]],
    latestTime: ['', [Validators.required]],
    guestLimit: ['', [Validators.required]],
    isRSVPOpen: false,
    isGuestPlusOne: false,
    isAutoApproveToGuestlist: false,
    isOnlyFacebookRSVP: false,
    isBirthdayAndPhoneRequired: false
  }),
  tickets: this.fb.group({
    info: this.fb.group({
      closingDate: '',
      closingTime: ''
    }),
    types: this.fb.array([])
  })
});

内部ngOnInit

this.eventSubscription = this.af.database.object('/events/' + this.eventId)
  .filter(event => event['$value'] !== null)
  .subscribe((event: IEvent) => {

    const settings: ISettings = event.settings;
    const collaborators: ICollaborator[] = settings.collaborators;
    const rsvp: IRSVP = settings.rsvp;
    const tickets: ITickets = settings.tickets;

    this.settingsForm.setValue({
      collaborators: collaborators || [],
      rsvp: rsvp,
      tickets: {
        info: tickets.info,
        types: tickets.types || []
      }
    });
  }
);

collaborators 包含一个值时,即它不是undefinednull 或空[],类似于:

[
  {
    email: 'foo@bar.com',
    role: 1
  },
  {
    email: 'baz@bar.com',
    role: 2
  }
]

然后应用程序在eventSubscription 中的setValue 行崩溃。

我无法弄清楚为什么会这样。

有什么想法吗?

【问题讨论】:

    标签: angular typescript angular2-forms angular2-formbuilder reactive-forms


    【解决方案1】:

    在 FormGroup 或 FormArray 上调用 setValue(data) 之前,FormGroup 或 FormArray 必须与data 具有完全相同相同的结构。只有结构很重要,FormGroup 或 FormArray 中的值将替换为data

    例如,如果您的数据是

    let data = [ {a: 1, b:2}, {a: 3, b: 4} ]
    

    那么FormArray 必须有2 个FormGroup,每个FormGroup 必须有一个名为a 的FieldControl 和一个名为b 的FieldControl。你可以这样做:

    let fa = this.formBuilder.array([
      this.formBuilder.group({a: 0, b:0}),
      this.formBuilder.group({a: 0, b:0})
    ])
    fa.setValue(data)
    

    如果您的数据结构更复杂,FormArray 需要具有相同的复杂结构。

    【讨论】:

      【解决方案2】:

      用控件初始化表单数组。那将解决问题。如果您需要知道如何操作,请参阅 Reactive Forms 指南。如果您使用的是ngModel,则可能值得将其删除。

      【讨论】:

        【解决方案3】:

        您必须在设置表单值之前构建表单 OnInit。试试这样的:

        settingsForm: FormGroup; 
        
        buildForm(): void {
           settingsForm: FormGroup = this.fb.group({
              //content of settingsForm
           })
        }
        
        ngOnInit() {
            this.buildForm();
            this.eventSubscription = this.af.database.object('/events/' + this.eventId)
            //...
            this.settingsForm.setValue({ //you can try .patchValue to set only available value
                //...
            })
        }
        

        【讨论】:

        • 这正是我正在做的事情。您不必在 on init 挂钩中执行此操作。
        • 好的,我有类似的问题,这解决了。我认为这是同一个问题 :(。你检查过这个blog post。引用:“如果你的 FormControl 存在,Angular 会移动到 Object.keys 循环,但是首先会通过 _throwIfControlMissing 检查该值是否缺少控件:"
        • 是的,这是缺少表单组的问题,所以我必须遍历所有对象,然后将一个新组推送到每个对象的表单数组。有点烦人和奇怪的设计选择。
        【解决方案4】:

        我认为这段代码会有所帮助

         import { FormArray, FormBuilder, FormGroup} from '@angular/forms';
        
        export class SomeComponent implements OnInit {
        
        consutructor(public  fb:FormBuilder) { }
        
            public buildcollaboratorsGroup(fb:FormBuilder):FormGroup {
                return fb.group({
                                    email:'',
                                    role:''
                        });
            }
        
        ngOnInit() {
            public settingsForm: FormGroup = this.fb.group({
            collaborators:this.fb.array([this.buildcollaboratorsGroup(this.fb)])
            });     
        
            this.setFormArrayValue();
         }
        
        
            // I am trying set only one value if it's multiple use foreach        
            public setFormArrayValue() {
                const controlArray = <FormArray> this.settingsForm.get('collaborators');
                controlArray.controls[0].get('email').setValue('yourEmailId@gmail.com');
                controlArray.controls[0].get('role').setValue(2);
            }
        
            // I am trying remove only one value if it's multiple use foreach        
            public removeFormArrayValue() {
                const controlArray = <FormArray> this.settingsForm.get('collaborators');
                   controlArray.removeAt(0);        
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2017-03-27
          • 2019-01-08
          • 2017-06-26
          • 1970-01-01
          • 2019-06-15
          • 1970-01-01
          • 2016-06-27
          • 2019-12-11
          • 1970-01-01
          相关资源
          最近更新 更多