【问题标题】:Angular 2 Add control to parent component's formAngular 2 将控件添加到父组件的表单
【发布时间】:2025-12-17 19:40:01
【问题描述】:

我有一个带有模板的自动完成功能:

<input [(ngModel)]="model"> //todo add control

实现如下:

<div class="form-group">
  <label for="location">Location</label>
  <auto-complete [(model)]="model.location"></auto-complete>
</div>

除此之外,我还有其他遵循这种格式的字段:(通知验证指令)

<div class="form-group" [fieldValidity]="biography">
  <label for="currentPassword">Biography</label>
  <textarea
    [(ngModel)]="model.biography" ngControl="biography" #biography="ngForm" maxlength="300"
    class="form-control" placeholder="About me..." rows="4"></textarea>
    <p class="xui-meta-info">
      We suggest a short bio. If it's 300 characters or less it'll look great on your profile.
    </p>
  <field-validation-messages [field]="biography"></field-validation-messages>
</div>

如您所见,我的验证指令依赖于在表单上具有关联控件的输入。如何确保我在自动完成中的输入在父表单中具有关联的控件? (我尝试以编程方式创建一个新的 Control() 然后调用 form.addControl() 但它只接受一个 NgControl

【问题讨论】:

  • “在输入上创建控件”是什么意思?
  • 在我的其他输入(在父组件中)我正在使用“ngControl="fullName" 等。我需要为此做类似的事情,我需要一个控件以使输入存在于父表单中这样我的验证(在父组件中)就可以使用 form.controls['location'].errors 例如。
  • 请提供更多代码来演示您尝试完成的工作。理想情况下是 Plunker。

标签: angular


【解决方案1】:

您需要通过实现自定义值访问器来使您的auto-complete 组件与控件兼容。

这是一个示例:

@Component({
  selector: 'auto-complete',
  template: `
    <input [(ngModel)]="model" (ngModelChange)="onChange($event)>
  `,
  (...)
})
export class AutoCompleteComponent implements AfterViewInit, ControlValueAccessor {

  onChange = (_) => {};
  onTouched = () => {};

  writeValue(value: any): void {
    this.model = value;
  }

  registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
  registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}

这样你就可以通过这种方式直接添加控制你的自动完成组件:

<auto-complete
  [(model)]="model.location"
  [ngFormControl]="someCtrl">
  <!-- or #autoComplete="ngForm" ngControl="autoComplete" -->
</auto-complete>

更多详情请看这篇文章(“NgModel兼容组件”一节):

这个问题也可以帮助你:

【讨论】:

  • 谢谢蒂埃里!我得到“'位置'没有值访问器”。有一个简单的解决方法吗?还是我需要编写自定义值访问器?
  • 如果我将其实现为 [ngFormControl]="location"。我收到一个错误“找不到控件''''。我猜那是因为我没有在我的父级上创建一个新的 Control()?我没有这样做的原因是因为我需要将控件添加到用于验证目的的表单,我注意到 form.addControl() 只接受 ngControl,不接受控制,所以我无法添加它。然后如果我将它实现为“#location="ngForm" ngControl="location",我得到错误:“‘位置’没有值访问器”。 location 在任何地方都不存在,我认为它会为我创建一个控件。
  • 是的,我认为你使用 #location="ngForm" ngControl="location 的方式是正确的,但你应用的元素必须支持控制。如果它是您的自动完成组件,则需要按照我的回答中所述实现自定义值访问器...