无法在 Angular 响应式表单中设置表单加载的默认值

Not able to set default values on Form Load in Angular Reactive Forms

基本上我需要通过传递id来执行http请求。收到回复后,我需要将值分配给表单字段。

我试过使用 setValue 和 patchValue。但是没用

sp服务

itemData = new ItemData()

    getItembyID(itemID) {
          return this.http.get<Object>(this.baseUrl +"items("+itemID+")")
          .pipe(map ((response : Response) => {
            const data = response['d']
            return data
          })
          ).subscribe((data : Response) => {
              this.setItemData(data)
          })
        }

    setItemData(data) {
        this.itemData.requestno  = data.Request_x0020_Number
        this.itemData.requestid  = data.Request_x0020_ID

编辑-form.component.ts

constructor(private spService : SharepointService,
                  private formBuilder : FormBuilder)

 ngOnInit() {
   this.route.params.subscribe((param : Params)=> {
            const id = param['ID']
            this.spService.getItemByID(ID)
       })

    this.itemData = this.sharepointService.itemData 
    // In console, I can see the details of the itemData but not able to set to the formcontrols.

    this.editForm = this.formBuilder.group({
       RequestNo : [''],
       RequestId : ['']
    })

    this.editForm.patchValue({
      RequestNo : this.itemData.requestno,
      RequestId : this.itemData.requestid

    })
    }   // End of OnInit

编辑-form.component.html


<form [formGroup]= "editForm">
  <label> DefaultRequestNo </label>
  <input type="text" formControlName="RequestNo">

   <label> DefaultRequestID </label>
    <input type="text" formControlName="RequestId">

</form>

这里的问题是您服务中的 itemData 无法同步使用,但您正在访问它,就好像它是同步的一样。您应该在您的服务中设置一个您的组件可以订阅的主题:

修改后的 SP 服务:

  itemData = new ItemData();
  private itemDataSource = new ReplaySubject<ItemData>(1);
  itemData$ = this.itemDataSource.asObservable();

  getItembyID(itemID) {
    return this.http.get<Object>(this.baseUrl +"items("+itemID+")")
      .pipe(map ((response : Response) => {
        const data = response['d']
        return data
      })
      ).subscribe((data : Response) => {
          this.setItemData(data)
      })
  }

  setItemData(data) {
    this.itemData.requestno  = data.Request_x0020_Number;
    this.itemData.requestid  = data.Request_x0020_ID;
    this.itemDataSource.next(this.itemData);
  }

那么您可以在您的组件中订阅:

// just do this once
this.editForm = this.formBuilder.group({
   RequestNo : [''],
   RequestId : ['']
})

this.sharepointService.itemData$.subscribe(itemData => {
  this.itemData = itemData;
  this.editForm.setVale({
    RequestNo : this.itemData.requestno,
    RequestId : this.itemData.requestid
  });
});

您的日志对您而言 "lying" 的原因;在您的服务中,您设置了一个初始对象值,然后只改变该对象。当您在控制台中记录一个对象时,它不会向您显示 'point in time' 值,它会向您显示对该对象的引用以及该引用中的值,因此即使数据在以下情况下实际上不可用您尝试设置表单值,当它最终被设置时,它仍然会出现在您的日志中。

这是为什么您应该在 Javascript 中避免对象突变的众多原因之一,而是每次更改时都实例化一个新对象,例如:

  setItemData(data) {
    this.itemData = Object.assign({}, this.itemData, {
      requestno: data.Request_x0020_Number,
      requestid: data.Request_x0020_ID
    });

    this.itemDataSource.next(this.itemData);
  }

此方法将确保您不会改变新对象,而是每次都创建一个新对象。这种特殊的方法可能不适合你的用例,但原理是一样的,不要变异。

您似乎在尝试手动设置默认值,而不是让 FormBuilder 管理它们。您应该尝试将上面的代码修改为:

this.editForm = this.formBuilder.group({
   RequestNo : [data.Request_x0020_Number],
   RequestId : [data.Request_x0020_ID]
})

应该可以。

要在编辑点击时设置默认值,可以使用@rxweb/reactive-form-validators中的FormBuilderConfiguration您可以设置来自 defaultValue 属性 中编辑 api 调用的值,如下所示:

 setItemData()
    {
           let user = new User();
         var formBuilderConfig = new FormBuilderConfiguration();
        formBuilderConfig.propsConfig = {'RequestNo':{defaultValue:"abc1"},"RequestId":{defaultValue:1}}
         this.editForm = <RxFormGroup>this.formBuilder.formGroup(user,formBuilderConfig);
    }

您需要在应用组件中导入RxReactiveFormsModule

这里是完整的组件代码

import { Component, OnInit } from '@angular/core';
import { FormGroup,FormArray } from "@angular/forms"
import { RxFormBuilder,RxFormGroup,FormBuilderConfiguration } from '@rxweb/reactive-form-validators';

import { User, } from './user.model';

@Component({
    selector: 'app-user',
    templateUrl: './patch-complete.component.html'
})
export class UserComponent implements OnInit {
    editForm: RxFormGroup

    constructor(
        private formBuilder: RxFormBuilder    ) { }

    ngOnInit() {
        let user = new User();
        this.editForm = <RxFormGroup>this.formBuilder.formGroup(user); 
         // this.itemData = this.sharepointService.itemData 
    // In console, I can see the details of the itemData but not able to set to the formcontrols.
    }
 
    setItemData()
    {
           let user = new User();
         var formBuilderConfig = new FormBuilderConfiguration();
        formBuilderConfig.propsConfig = {'RequestNo':{defaultValue:"abc1"},"RequestId":{defaultValue:1}}
         this.editForm = <RxFormGroup>this.formBuilder.formGroup(user,formBuilderConfig);
    }
}
<div>

   <form [formGroup]= "editForm">
  <label> DefaultRequestNo </label>
  <input type="text" formControlName="RequestNo">
<br/>
   <label> DefaultRequestID </label>
    <input type="text" formControlName="RequestId">
    <br/>
<button (click)="setItemData()">SetItemData</button>
</form>
</div>

这是Working Example