【问题标题】:How to use ngModel with a custom control inside a form?如何在表单内使用带有自定义控件的 ngModel?
【发布时间】:2017-06-15 11:41:25
【问题描述】:

我创建了一个处理选择框的组件,现在当我在提交表单后将它放入表单标签时,选择的结果不会显示在控制台中。

我的代码有什么问题?我该如何解决这个问题?

  • testOption: 是我传递的对象数组,用@Input 抛出选择框。

这里是选择框组件:

import { Component, OnInit, Input } from '@angular/core';

@Component({
    selector: 'input-select',
    template:`
      <div class="field-select">
        <span><icon name="select-arrow" size="10"></icon></span>
        <select name="{{name}}" class="field">
          <option value="0" disabled selected>{{label}}</option>
          <option *ngFor="let option of options" [ngValue]="option.value">{{option.name}}</option>
        </select>
      </div>
    `
})
export class InputSelectComponent implements OnInit {
    @Input() label: string;
    @Input() name: string;
    @Input() options;


    // testOptions = [
    //   {value:'test',name:'test2'},
    //   {value:'test',name:'test2'}
    // ];

    constructor() { }

    ngOnInit() {
      console.log(this.options);
     }

}

在html中的使用:

<input-select label="test" name="select2" [options]="testOption"></input-select>

表单 html:

<form role="form" class="form" #f="ngForm" (ngSubmit)="onSubmit(f)">
    <input class="field" name="name" ngModel type="text" placeholder="n1">
    <input-select label="b2" name="select2" [options]="testObject"></input-select>
    <input class="field" name="building-type" type="text" ngModel placeholder="b3">
</form>

控制台日志:(没有选择框值)

Object {name: "test", building-type: "tset" }

【问题讨论】:

  • 你说的是testOptiontestObject。正确的名字是什么? :) 先检查一下..
  • @mxii 正确的名称是 testOption。我的坏:)
  • 请显示您的“父”组件。 (模板)
  • 它将undefined 记录到控制台? result of selection 是什么意思。我没有看到任何可以将结果打印到控制台的代码。 :)
  • @mxii 我更新了问题。

标签: angular angular2-template angular2-forms


【解决方案1】:

我想我现在遇到了你的问题。

您想在自定义组件上实现ControlValueAccessor 以在带有ngModel! 的表单内使用它?

您的组件应如下所示:

@Component({
   selector: 'ng2-input-select',
   template: `
      <div class="field-select">
        <select name="{{ name }}" class="field" [(ngModel)]="value" (ngModelChange)="_onChange($event)">
          <option value="" disabled selected>{{ label }}</option>
          <option *ngFor="let option of options" [value]="option.value">{{ option.name }}</option>
        </select>
      </div>
   `,
   providers: [
      { /* idk why or what this will do exactly.. but it works! ;) */
         provide: NG_VALUE_ACCESSOR,
         useExisting: forwardRef(() => SelectBoxComponent),
         multi: true
      }
   ]
})
export class SelectBoxComponent implements OnInit, ControlValueAccessor {
  @Input() label: string;
  @Input() name: string;
  @Input() options;
  @Input() value: string = '';

  // ControlValueAccessor implementation
  // ====================================

  // call if value was changed inside our component
  private _onChange = (_: any) => { };
  // call if input was "touched" .. !
  private _onTouched = () => { };

  // incoming change..
  public writeValue(val: any) {
    this.value = val;
  }

  public registerOnChange(fn: (_: any) => void): void { this._onChange = fn; }
  public registerOnTouched(fn: () => void): void { this._onTouched = fn; }
}

现场演示:https://plnkr.co/edit/imCJmCoJaeGQiUMcyBwz?p=preview

更新

在表单组件中使用更改检测:

<ng2-input-select ngModel (ngModelChange)="selectBoxChanged($event)" label="b2" name="select2" [options]="testObject"></ng2-input-select>

【讨论】:

  • 感谢您的回答。我还有一个问题,如何在另一个组件中调用registerOnChange函数?
  • 为什么要这样做? :) 你想达到什么目标?
  • 我想检测不同组件和不同对象的选择框的变化。基本上我想使用registerOnChange 函数。
  • 您不应该使用此功能。请参阅我更新的更改检测答案。它与使用 ngModel 的其他表单输入相同。
  • 嗨@mxii 我想知道为什么使用 controlvalueaccessor 方法而不是其他类型的组件通信?例如服务或 viewchild 或输入和输出。你能详细说明这个问题吗?也许我应该把它当作一个问题。
【解决方案2】:

试试[value]="option.value",顺便说一句,你能不能也展示一下你的控制台

【讨论】:

    【解决方案3】:

    您必须将 ngModel 绑定为选择器中的属性之一。然后在控制台中打印 ngModel 值。

    【讨论】:

    • 在组件选择器上绑定 ngModel 后出现此错误:EXCEPTION: Uncaught (in promise): Error: No value accessor for form control with name: 'select2'
    • 您必须在选择器中包含表单。从“@angular/forms”导入 {FormGroup}。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 2013-07-24
    • 2019-09-15
    • 1970-01-01
    相关资源
    最近更新 更多