如何动态添加FormArray项并正确绑定控件和模型?

时间:2018-10-28 20:26:57

标签: angular typescript

我有一个日历,它本质上代表着一种巨大的形式。目前没有什么可看的,但是现在它会得到dates的清单,我将根据清单开始建立表格:

this.dates.forEach(d => {
  group[d] = this._formBuilder.group({
    offers: this._formBuilder.array([])
  });
});

所以,我真正想要的是:从日期到项目列表的映射

{
  '2018-01-01': [{id: 1}, {id: 2}],
  '2018-01-02': [{id: 5}, {id: 9}]
}

但是,在this tutorial之后,我似乎最终会遇到类似这样的情况:

{
  '2018-01-01': {offers: [{id: 1}, {id: 2}]},
  '2018-01-02': {offers: [{id: 5}, {id: 9}]}
}

这对我来说足够好-我只希望它能正常工作。

我正在传递父组件中的offers表单组:

<form [formGroup]="form" *ngIf="form != null">  
  <div fxLayout="row" >  
    <app-calendar-day *ngFor="let date of dates$ | async" 
                      [formGroup]="form.get(date)">
    </app-calendar-day>  
  </div>  
</form>

到目前为止,这是可行的。

我的问题始于我要向FormArray添加商品/商品的最后一步。

<div [formGroup]="formGroup">
  <mat-card *ngFor="let offer of formGroup.get('offers').controls; let idx = index" style="margin: 4px; padding: 10px;">
    <app-offer-item [formGroupName]="idx">
    </app-offer-item>
  </mat-card>
</div>

日历允许添加项目/要约,我希望formGroup.get('offers')FormArray)可以动态建立。我可以在当天结束时发布整个内容。

但是,我不知道如何正确绑定商品/项目。

app-offer-item建立在AbstractControlComponent的基础上,它提供了ControlValueAccessorValidator接口以及一些默认实现。 OfferItemComponentapp-offer-item的代码如下。由于它封装了一个对象,因此我可以确定该元素应该表示一个FormGroup,但是我似乎无法正确地将它们连接在一起。

上面的代码给了我

  

错误错误:找不到具有未指定名称属性的控件

这似乎是在我将商品/要约添加到FormArray后发生的:

onAddOffer(offer) {
  const formArray = <FormArray> this.formGroup.get('offers');
  formArray.push(this._formBuilder.group(offer));
  // ..
}

我希望writeValue()中的OfferItemComponent会以某种方式被调用,但我想那不是它的工作原理。

我想我有两个选择:

  1. 找到一种使这项工作最终完成的方法
  2. 将附加的FormGroup传递到OfferItemComponent并尝试使其像这样

非常感谢您的帮助!


OfferItemComponent

@Component({
  selector: 'app-offer-item',
  styles: [`
  `],
  template: `
    <div>      
      <div [innerHTML]="getItemHtml()"></div>

      <div>
        <span style="padding-right: 4px;">€</span>
        <mat-form-field style="text-align: right; width: 55px; margin-bottom: -1.25em;">
          <input matInput autocomplete="off" (focusout)="formatPrice($event.target)"/>
        </mat-form-field>        
      </div>

    </div>
  `,
  providers: [
    DecimalPipe,
    ValueAccessorProvider(OfferItemComponent),
    ValidatorsProvider(OfferItemComponent)
  ]
})
export class OfferItemComponent extends AbstractControlComponent {
  @Input()
  items;

  offer: OfferModel;

  constructor(
    @Inject(LOCALE_ID) public locale: string,
    private _decimalPipe: DecimalPipe
  ) {
    super();
  }

  writeValue(offer: OfferModel): void {
    this.offer = offer;
    this._onChangeCallback(this.offer);
  }

  validate(c: AbstractControl): ValidationErrors | any {
    // ..
  }

  getItemHtml() {
    // ..
  }

  formatPrice(element) {
    // ..
  }

}

2 个答案:

答案 0 :(得分:1)

我相信[formGroup]中的所有表单控件元素也需要设置“名称”和“ formControlName”属性。

[attr.data-name]="name_of_field" [formControlName]="name_of_field"

答案 1 :(得分:0)

  

代码中缺少的元素是formArrayName

<div formArrayName="offers">
  <mat-card *ngFor="let offer of formGroup.get('offers').controls; let idx = index" style="margin: 4px; padding: 10px;">
    <app-offer-item [formGroupName]="idx">
    </app-offer-item>
  </mat-card>
</div>