Angular 2错误:找不到具有未指定名称属性的控件 - 组件内部的组件

时间:2017-07-29 17:52:42

标签: forms angular typescript

我必须创建一个表单,并且我想更清楚地了解组件

形式的主要思想是:

FormComponent | >     FieldComponent       | > Form的InputComponent

所以我有PartnerFormComponent:

HTML:

 <form [formGroup]="partnerForm" (ngSubmit)="save()">
    <!--<legal-information
      [(partner)]="partner" [(partnerConfiguration)]="partnerConfiguration" ></legal-information>-->
    <combo-billing-entity [(formGroup)]="partnerForm"       [(partner)]="partner" [(partnerConfiguration)]="partnerConfiguration"></combo-billing-entity>

    <div class="buttons_form">
      <button class="save_button_form" type="submit" [disabled]="!partnerForm.valid">
        Add
      </button>

      <a class="btn-floating btn-large waves-effect waves-light green"
         routerLink="/partners">
        <i class="material-icons">Cancel</i>
      </a>
    </div>
  </form>

和ts:

@Component({
  selector: 'partner-form',
  templateUrl: './partner-form.component.html',
  styleUrls: ['./partner-form.component.css'],
  entryComponents:[LegalInformationComponent]
})
export class PartnerFormComponent implements OnInit {


  private partnerForm: FormGroup;
  title: string;
  partner: Partner = new Partner();
  partnerConfiguration: PartnerConfiguration = new PartnerConfiguration();

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private partnerService: PartnerService
  ) {  }



  ngOnInit() {
    var id = this.route.params.subscribe(params => {
      var id = params['id'];

      if (!id)
        return;

      .....

    });
  }

然后从组件我有html Combo:

  <div class="components_situation">
    <div class="field_form_title">
      {{title}} <span class="is_required_form" [hidden]="!isRequired">*</span>
    </div>
    <div [formGroup]="formGroup" >
    <select id="billingEntity" [(ngModel)]="partnerConfiguration.fakeBillingEntity"
            formControlName="billingEntity"
            [class.invalid]="form.controls['billingEntity'].touched && !form.controls['billingEntity'].valid"
    >
      <option disabled hidden [value]="selectUndefinedOptionValue">-- select --</option>
      <option *ngFor="let obj of billingEntities" [value]="obj.value" >{{obj.name}}</option>
    </select>
    </div>
    <div class="some_explanation_form_field">{{someExplanation}}</div>
  </div>

和TS:

import {Component, Input, OnInit} from "@angular/core";
import {CommonFieldFormComponent} from "../../common-field-form-component";
import {BillingService} from "../../../../../../services/billing/billing.service";
import {BillingEntitity} from "../../../../../../model/billing_entity";
import {FormBuilder, FormGroup, Validators} from "@angular/forms";

@Component({
  selector: 'combo-billing-entity',
  templateUrl: './combo-billing-entity.component.html'
})
export class ComboBillingEntityComponent extends CommonFieldFormComponent implements OnInit {
  private selectUndefinedOptionValue:any;
  billingEntities:BillingEntitity[] = [];

  @Input()
  private formGroup:FormGroup;


  constructor(private billingService: BillingService, private formBuilder:FormBuilder)
 {
   super();
   this.isRequired=true;
   this.title="Billing Entity";
   this.someExplanation="Identifies entity responsible for billing invoice";
   this.formGroup = this.formBuilder.group({
      billingEntity :['', Validators.required]
    });
  }

但毕竟我有这个错误:

ComboBillingEntityComponent.html:5错误错误:找不到具有未指定名称属性的控件     at _throwError(forms.es5.js:1852)     at setUpControl(forms.es5.js:1760)     在FormGroupDirective.webpackJsonp ... / .. / .. / forms/@angular/forms.es5.js.FormGroupDirective.addControl(forms.es5.js:4733)     在FormControlName.webpackJsonp ... / .. / .. / forms/@angular/forms.es5.js.FormControlName._setUpControl(forms.es5.js:5321)     在FormControlName.webpackJsonp ... / .. / .. / forms/@angular/forms.es5.js.FormControlName.ngOnChanges(forms.es5.js:5239)     at checkAndUpdateDirectiveInline(core.es5.js:10831)     at checkAndUpdateNodeInline(core.es5.js:12330)     at checkAndUpdateNode(core.es5.js:12269)     在debugCheckAndUpdateNode(core.es5.js:13130)     在debugCheckDirectivesFn(core.es5.js:13071)

任何想法如何将输入绑定到主要表单..我做错了什么?

2 个答案:

答案 0 :(得分:0)

您的组件必须实现ControlValueAccessor并注册它是一个多依赖项。 Pascal Precht在custom form controls in Angular上有一篇非常好的博文。

简而言之,在通过定义函数ControlValueAccessorwriteValueregisterOnChange来实现registerOnTouched之后,您必须提供现有值,以便Angular可以知道你正试图将它用作表单控件。

@Component({
  // ...
  providers: [
    { 
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ComboBillingEntityComponent),
      multi: true,
    }
  ],
  // ...
})
class ComboBillingEntityComponent implements ControlValueAccessor {
  // ...
}

在此之后,您可以在模板中的formControlName标记上使用<combo-billing-entity>

<combo-billing-entity formControlName="billingInfo"></combo-billing-entity>

答案 1 :(得分:0)

您的表单中有很多问题。您正尝试在输入字段中使用双向绑定,例如[(formGroup)]="partnerForm"但是您无法使用@Output实际触发双向绑定,因此您没有正确使用它

表单对象确实是一个对象,对象在JS中是可变的并通过引用传递。有时这不是理想的行为,但在这种情况下,我们需要这样,我们有嵌套组件。所以,无论你在子组件中形成字段,父母都会知道,所以你实际上并不需要双向绑定。

其次,请避免在被动形式中使用[(ngModel)]。我注意到可能会发生奇怪的行为,这是可以理解的,因为我们有两个绑定到ngModel变量,另一个是表单控制变量。改为使用表单控件,并从模板中删除所有ngModel。您可以将值设置为表单控件,它基本上可以作为双向绑定使用,因为您可以随时从TS访问表单控件值。所以[(ngModel)]

在父级中构建整个表单,然后将表单组传递给子级,或者将嵌套的表单组传递给您的孩子。因此,在您的父级中,您实际上想要构建表单:

this.partnerForm = this.fb.group({
  billingEntity: ['hey I am initial value']
})

您可以将初始值设置为billingEntity,或者如果您需要在某个其他位置手动设置默认值,您可以通过以下方式执行此操作:this.partnerForm.get('billingEntity').setValue(...)

我们现在将此表单传递给孩子:

<combo-billing-entity [partnerForm]="partnerForm"></combo-billing-entity>

在孩子中我们将其注册为Input

@Input() formGroup: FormGroup;

然后我们可以使用它,例如:

<div [formGroup]="partnerForm">
  <input formControlName="billingEntity" />
</div>

我看到你正在尝试使用[(ngModel)],但如上所述,你可以删除它并使用表单控件。该值很好地存储在formGroup.get('billingEntity').value中,如前所述,如果需要在某个时刻设置值,则可以这样做。但是所有表单值都很好地存储在表单对象中,即partnerForm.value

这是一个简单的演示:http://plnkr.co/edit/AuidEMaaURsBPfDP8k0Q?p=preview

我建议你阅读有关嵌套表单的内容,这个非常适合开始使用:Nested Model-driven Forms