【问题标题】:Angular2 set value for formGroupAngular2为formGroup设置值
【发布时间】:2016-12-03 23:33:54
【问题描述】:

所以我有一个用于创建实体的复杂表单,我也想用它来编辑,我正在使用新的角度表单 API。我将表单的结构与我从数据库中检索的数据完全一样,所以我想将整个表单的值设置为检索到的数据,这里是我想要做的一个例子:

this.form = builder.group({
      b : [ "", Validators.required ],
      c : [ "", Validators.required ],
      d : [ "" ],
      e : [ [] ],
      f : [ "" ]
    });
this.form.value({b:"data",c:"data",d:"data",e:["data1","data2"],f:data});

PS:NgModel 不适用于新表单 api,我也不介意在模板中使用一种方式数据绑定,如

<input formControlName="d" value="[data.d]" />

这行得通,但在数组的情况下会很痛苦

【问题讨论】:

标签: angular angular2-forms


【解决方案1】:

可以使用form.get获取具体的控件对象,使用setValue

this.form.get(<formControlName>).setValue(<newValue>);

【讨论】:

  • 如何将数组传递给新值
【解决方案2】:

要设置 所有 FormGroup 值使用,setValue

this.myFormGroup.setValue({
  formControlName1: myValue1, 
  formControlName2: myValue2
});

要设置部分值,请使用patchValue

this.myFormGroup.patchValue({
  formControlName1: myValue1, 
  // formControlName2: myValue2 (can be omitted)
});

使用第二种技术,不需要提供所有值,未设置值的字段不会受到影响。

【讨论】:

  • 我在嵌套表单中使用 patchValue,它会覆盖表单中的所有字段。 (即使是我没有指定的)知道我做错了什么吗?
  • @Enrico,没有你的代码我帮不了你。
【解决方案3】:

是的,您可以使用 setValue 来设置值以进行编辑/更新。

this.personalform.setValue({
      name: items.name,
      address: {
        city: items.address.city,
        country: items.address.country
      }
    });

您可以参考http://musttoknow.com/use-angular-reactive-form-addinsert-update-data-using-setvalue-setpatch/ 了解如何使用响应式表单通过 setValue 进行添加/编辑功能。它节省了我的时间

【讨论】:

    【解决方案4】:

    当你的控件是FormGroup的时候设置值可以用这个例子

    this.clientForm.controls['location'].setValue({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude
        });
    

    【讨论】:

      【解决方案5】:

      正如 cmets 中所指出的,在提出此问题时不支持此功能。这个问题已经在 angular 2 rc5 中解决了

      【讨论】:

        【解决方案6】:

        我已经实现了一个临时解决方案,直到 angular2 支持表单 updateValue

         initFormGroup(form: FormGroup, data: any) {
                for(var key in form.controls) {
                  console.log(key);
                  if(form.controls[key] instanceof FormControl) {
                    if(data[key]){
                      let control = <FormControl>form.controls[key];
                      this.initFormControl(control,data[key]);
                    }
                  } else if(form.controls[key] instanceof FormGroup) {
                    if(data[key]){
                      this.initFormGroup(<FormGroup>form.controls[key],data[key]);
                    }
                  } else if(form.controls[key] instanceof FormArray) {
                    var control = <FormArray>form.controls[key];
                    if(data[key])
                    this.initFormArray(control, data[key]);
                  }
                }
              }
              initFormArray(array: FormArray, data: Array<any>){
            if(data.length>0){
              var clone = array.controls[0];
              array.removeAt(0);
              for(var idx in data) {
                array.push(_.cloneDeep(clone));
                if(clone instanceof FormGroup)
                  this.initFormGroup(<FormGroup>array.controls[idx], data[idx]);
                else if(clone instanceof FormControl)
                  this.initFormControl(<FormControl>array.controls[idx], data[idx]);
                else if(clone instanceof FormArray)
                  this.initFormArray(<FormArray>array.controls[idx], data[idx]);
              }
            }
          }
        
        
        initFormControl(control: FormControl, value:any){
            control.updateValue(value);
          }
        

        用法:

        this.initFormGroup(this.form, {b:"data",c:"data",d:"data",e:["data1","data2"],f:data});
        

        注意:表单和数据必须具有相同的结构,我使用 lodash 来深度克隆 jQuery,其他库也可以这样做

        【讨论】:

          【解决方案7】:

          “NgModel 不适用于新表单 api”。

          那不是真的。你只需要正确使用它。如果您使用的是响应式表单,则应响应式指令一起使用 NgModel。见the example in the source

          /*
           * @Component({
           *      selector: "login-comp",
           *      directives: [REACTIVE_FORM_DIRECTIVES],
           *      template: `
           *        <form [formGroup]="myForm" (submit)='onLogIn()'>
           *          Login <input type='text' formControlName='login' [(ngModel)]="credentials.login">
           *          Password <input type='password' formControlName='password'
           *                          [(ngModel)]="credentials.password">
           *          <button type='submit'>Log in!</button>
           *        </form>
           *      `})
           * class LoginComp {
           *  credentials: {login:string, password:string};
           *  myForm = new FormGroup({
           *    login: new Control(this.credentials.login),
           *    password: new Control(this.credentials.password)
           *  });
           *
           *  onLogIn(): void {
           *    // this.credentials.login === "some login"
           *    // this.credentials.password === "some password"
           *  }
           * }
           */
          

          虽然它看起来像来自 TODO comments,但它可能会被删除并替换为反应式 API。

          // TODO(kara):  Replace ngModel with reactive API
          @Input('ngModel') model: any;
          

          【讨论】:

          • 来自 angular2 api docs NgModel 选择器 [ngModel]:not([formControlName]):not([formControl]) angular.io/docs/ts/latest/api/forms/index/… 所以即使它现在有效,我想我会在以后删除它实施手动值注入器,因为这将是一个更稳定的解决方案
          • @AmgadSerry 是为了确保它不会干扰这些组件(在选择器中)。 FormControlName 明确地将其添加为 @Input()。请参阅我链接到的来源。如果那些否定选择器不存在,那么在上面的示例中,将创建一个 NgModel,这是您不想要的。
          • 这有点令人困惑,但这就是它的实现方式。对于FormControlDirective ([formControl]) 和FormControlName (formControlName),这就是它的工作原理。如果ngModel 没有使用其中之一,则假定您将使用声明性 表单,并创建NgModel。如果ngModel其中一个reactive表单指令一起使用,那么那个响应式表单指令将处理模型,而不是@987654335 @
          • 哦,我以为他们只是为了暂时在这两个指令上启用 ngModel 而他们将其删除
          • 检查我当前的解决方案
          猜你喜欢
          • 1970-01-01
          • 2017-06-11
          • 1970-01-01
          • 2019-02-19
          • 1970-01-01
          • 2017-11-13
          • 2017-11-09
          • 2017-12-09
          • 1970-01-01
          相关资源
          最近更新 更多