首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >角- setValue formArrayName

角- setValue formArrayName
EN

Stack Overflow用户
提问于 2019-12-24 13:49:10
回答 2查看 1.1K关注 0票数 1

我有一个包含字符串数组的表单,每当我向列表中添加一个元素时,问题是当我使用setValue在数组中设置值时,它会显示以下错误

代码语言:javascript
复制
<button (click)="addNewCompany()">Add new Company</button><br><br>
<form [formGroup]="myForm">
    <div formArrayName="companies">
        <div *ngFor="let comp of getForm(); let i=index>
            <fieldset>
                <legend>
                    <h3>COMPANY {{i+1}}: </h3>
                </legend>
                <label>Company Name: </label>
                <input [formControlName]="i" /><span><button (click)="deleteCompany(i)">Delete Company</button></span>
            </fieldset>
        </div>
    </div><br>
  </form>


export class AppComponent implements OnInit {

  @Input()
  public product: Product; 

  myForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      companies: this.fb.array([])
    });
  }

  ngOnInit() {
     this.addNewCompany();
     this.myForm.controls['companies'].setValue(this.product.companies); // error
  }

  getForm(): any {
    return this.myForm.get("companies")["controls"];
  }

  addNewCompany() {
    const control = <FormArray>this.myForm.get("companies");
    control.push(this.fb.control(''));
  }

  deleteCompany(index) {
    let control = <FormArray>this.myForm.controls.companies;
    control.removeAt(index);
  }

}

错误:还没有在此数组中注册的窗体控件。如果您正在使用ngModel,您可能需要检查下一个滴答(例如,使用setTimeout)。

stackblitz

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-24 14:05:20

如果尝试从控件设置companies,则该值必须是数组,并确保添加数组值的新窗体控件基。

代码语言:javascript
复制
product = {
companies:['company 01' , 'company 02']
} 
代码语言:javascript
复制
ngOnInit() {
  // make sure you have set a default value to product like {companies:[]}
  for (let p of this.product.companies) {
    this.addNewCompany();
  }

  this.myForm.controls['companies'].setValue(this.product.companies);
}

如果使用setValue方法,则必须提供控件长度的值基,否则会在数组控件长度小于或大于数组控件长度时抛出错误,数组值必须与控件长度相同。 patchValue 没有关于控制长度的约束,但这意味着如果将公司设置为10,而您只有一个控件,则只会得到第一家公司,而另一家将因此消失,在这种情况下,请确保使用setValue或patchValue,但确保有长度与值相同的控件。

演示

票数 0
EN

Stack Overflow用户

发布于 2019-12-24 14:34:05

您可以将创建form的逻辑移动到ngOnInit中。就像这样:

代码语言:javascript
复制
@Input()
public product: Product;

myForm: FormGroup;

constructor(private fb: FormBuilder) {}

ngOnInit() {
  this.myForm = this.fb.group({
    companies: this.fb.array(this.product ? this.product.companies.map(company => new FormControl(company)) : [])
  });
}

addNewCompany() {
  this.companies.push(new FormControl());
}

deleteCompany(i) {
  this.companies.removeAt(i);
}

get companies() {
  return ( < FormArray > this.myForm.get('companies'));
}

但是,可能无法保证product @Input属性将按时间设置。

因此,为了确保在使用companies FormArray创建companiesFormArray之前设置了该属性,您可能需要通过服务来初始化其中的product属性。

您必须创建一个为您执行此任务的DataService

代码语言:javascript
复制
import { Injectable } from '@angular/core';
import { Product } from './product.model';

@Injectable()
export class DataService {

  product: Product;

  constructor() { }

  setProduct(product) {
    this.product = product;
  }

}

然后,您可以将其注入父组件以设置product,并将其注入子组件中以获得ngOnInit生命周期钩子方法中的产品。就像这样:

代码语言:javascript
复制
myForm: FormGroup;

constructor(
  private fb: FormBuilder,
  private dataService: DataService
) {}

ngOnInit() {
  this.myForm = this.fb.group({
    companies: this.fb.array(this.dataService.product ? this.dataService.product.companies.map(company => new FormControl(company)) : [])
  });
}

addNewCompany() {
  this.companies.push(new FormControl());
}

deleteCompany(i) {
  this.companies.removeAt(i);
}

get companies() {
  return ( < FormArray > this.myForm.get('companies'));
}

这是一个供您参考的工作样品演示

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59469780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档