Angular 角度5-可观察-将可观察的第一个值设置为formgroup

Angular 角度5-可观察-将可观察的第一个值设置为formgroup,angular,forms,observable,Angular,Forms,Observable,在我的onInit方法中,我确实有一个可观察的联系人,我也会将可观察联系人的第一个联系人设置到我的表单中。 有人知道怎么做吗 ngOnInit() { let contactsObservable: Observable<Contact[]> = this.contactService.getAllContacts(); contactsObservable.subscribe(contacts => { this.contacts

在我的onInit方法中,我确实有一个可观察的联系人,我也会将可观察联系人的第一个联系人设置到我的表单中。 有人知道怎么做吗

ngOnInit() { 
    let contactsObservable: Observable<Contact[]> = 
    this.contactService.getAllContacts();
    contactsObservable.subscribe(contacts => {
        this.contacts = contacts; 
    });

    this.form = this.fb.group({ 
                // this.contacts[0] does not work
      contact: [this.contacts[0], [Validators.required]] // how to get contact[0] into form for presetting
    });
}
ngOnInit(){
让联系人可观察:可观察=
this.contactService.getAllContacts();
ContactsBServable.subscribe(联系人=>{
这个。联系人=联系人;
});
this.form=this.fb.group({
//此。联系人[0]不工作
联系人:[this.contacts[0],[Validators.required]]//如何将联系人[0]设置为表单以进行预设
});
}

理想情况下,表单应该位于从中获取数据的子组件中。然后,您可以使用管道将
contactsObservable
直接传递到表单,并同步使用这些值

但是,为了在相同的
OnInit
hook中完成这一切,最好的方法是为您的
contactsAbservable
提供一个值。只有在您知道每种情况下第一个值是什么的情况下,这才是可行的,并且如果您已经知道了这一点,您还可以使用有效的起始值实例化表单控件:

this.form = this.fb.group({ 
  contact: [[ // some value ], [Validators.required]]
});
您可以像罗兰在评论中提到的那样在订阅中初始化表单,但这将在每次可观察对象发出值时重新初始化表单。类似地,在订阅中强制设置表单控件的值可能会覆盖用户输入的输入或其他古怪行为,具体取决于服务的工作方式

这种方法的示例如下所示

contactsObservable.subscribe(contacts => {
  this.form = this.fb.group({
    contacts: [contacts, [...Validators]]
  })
});

注:您可以使用或根据需要使用。但是这种方法仍然是错误的,因为它试图忽略数据的异步性质。而且它将覆盖当前输入中的任何内容,因此,如果在用户键入时更新数据,他们的输入将被清除和替换,这可能会令人沮丧。另外,您还需要处理订阅的清理


此模式不能按预期工作的主要原因是,您将异步值
contacts
视为是同步的。仅仅通过在组件中解包并将值保存到变量,并不能消除通过可观察对象到达的值的异步性质。查看更多信息

在我看来,最好的办法是将表单提取到一个单独的组件中,并利用Angular的
async
管道来传递异步数据。

您将获得异步联系人。 当可观察到返回值时,可以输入值

ngOnInit() { 
   this.form = this.fb.group({ 
     contact: ['', [Validators.required]] 
   });
   let contactsObservable: Observable<Contact[]> = 
   this.contactService.getAllContacts();
   contactsObservable.subscribe(contacts => {
       this.contacts = contacts; 
       this.form.controls['contact'].setValue(this.contacts[0])
   });
}
ngOnInit(){
this.form=this.fb.group({
联系人:['',[需要验证人]]
});
让联系人可观察:可观察=
this.contactService.getAllContacts();
ContactsBServable.subscribe(联系人=>{
这个。联系人=联系人;
this.form.controls['contact'].setValue(this.contacts[0])
});
}

为什么不将
表单的初始化放在
subscribe()
中呢

或者,您可以在不与
联系的情况下初始化表单
,然后将其添加到
表单组

这将通过异步进行,但您可以在模板中设置
*ngIf
,如下所示:

<form *ngIf="form" ...>...</form>
。。。

您可以使用Form patchValue来设置表单,正如VinceCompanale所指出的,最好使用智能/哑组件模式,然后在您的组件中进行设置

  @Input() set contactsList(contacts: any[]) {
    if (contacts) {
      this.form.patchValue({
        contact: contacts[0]
      });
    }
  }

这对我来说很有用,Angular 6.x:

 import {FormBuilder, FormGroup, Validators} from '@angular/forms';
 @Input() artist: Artist;
 artistForm: FormGroup;
 constructor(private route: ActivatedRoute, private artistService: ArtistService, private location: Location, private fb: FormBuilder)  { this.createForm(); }


 ngOnInit() {
 this.getArtist();
}

   createForm(){
this.artistForm = this.fb.group({
  ArtistName: ['', Validators.required]

 });
}


   getArtist(): void{
const id = +this.route.snapshot.paramMap.get('id');
this.artistService.getArtist(id).pipe(tap(artist => this.artistForm.setValue({ArtistName: artist.ArtistName}))).subscribe(artist => {
  artist = this.artist;
  });

}
现在,html:

   <h2>Artist Information</h2>
  <form [formGroup]="artistForm">
  <div class="form-group">
  <label class="center-block">Artist Name:

    <input class="form-control" formControlName="ArtistName">
  </label>
</div>
艺术家信息
艺人姓名:

这是一种巧妙的方法。我学到了一些新东西。赞成票:)
 import {FormBuilder, FormGroup, Validators} from '@angular/forms';
 @Input() artist: Artist;
 artistForm: FormGroup;
 constructor(private route: ActivatedRoute, private artistService: ArtistService, private location: Location, private fb: FormBuilder)  { this.createForm(); }


 ngOnInit() {
 this.getArtist();
}

   createForm(){
this.artistForm = this.fb.group({
  ArtistName: ['', Validators.required]

 });
}


   getArtist(): void{
const id = +this.route.snapshot.paramMap.get('id');
this.artistService.getArtist(id).pipe(tap(artist => this.artistForm.setValue({ArtistName: artist.ArtistName}))).subscribe(artist => {
  artist = this.artist;
  });

}
   <h2>Artist Information</h2>
  <form [formGroup]="artistForm">
  <div class="form-group">
  <label class="center-block">Artist Name:

    <input class="form-control" formControlName="ArtistName">
  </label>
</div>