Angular 2:'控制值访问器'在嵌套元素上

时间:2017-04-15 10:33:38

标签: angular angular2-template angular2-forms

我有一个控制值访问器'从这里上课http://blog.rangle.io/angular-2-ngmodel-and-custom-form-components/

export class ValueAccessorBase<T> implements ControlValueAccessor {
  private innerValue: T;
  private changed = new Array<(value: T) => void>();
  private touched = new Array<() => void>();

  get value(): T {
    return this.innerValue;
  }
  set value(value: T) {
    if (this.innerValue !== value) {
      this.innerValue = value;
      this.changed.forEach((f) => f(value));
    }
  }
  touch() {
    this.touched.forEach((f) => f());
  }
  writeValue(value: T) {
    this.innerValue = value;
  }
  registerOnChange(fn: (value: T) => void) {
    this.changed.push(fn);
  }
  registerOnTouched(fn: () => void) {
    this.touched.push(fn);
  }
}

我在一个组件中扩展该类:

export class PricingComponent extends ValueAccessorBase<any> implements OnInit {
  constructor() {
    super(); // value accessor base
  }
}

使用PricingComponent内部ngModelGroup模板将多个输入表单控件分组到一个对象中:

  <div ngModelGroup="value">
    <md-select [(ngModel)]="value.type" name="type">
      <md-option *ngFor="let c of list" [value]="c.code">{{c.dsc}}</md-option>
    </md-select>
    <md-input-container>
      <input [(ngModel)]="value.amount" name="amount" mdInput>
    </md-input-container>
  </div>

PricingComponent使用如下:

<form #form="ngForm">
  <app-pricing name="prices" ngModel></app-pricing>
  {{form.value | json}}
</form>

现在,我想从form.value获得的内容如下:

{ prices: { type: 'high', amount: 542 } }

但是我收到了这个错误:

No provider for ControlContainer

2 个答案:

答案 0 :(得分:0)

您需要将PricingComponent添加到NG_VALUE_ACCESSOR列表中。所以在组件元数据中添加:

providers: [
  {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => PricingComponent),
    multi: true
  }
]

答案 1 :(得分:0)

不确定这是最好的方法,但是我通过不扩展ValueAccessorBase类来解决它,而是使用ngModelGroup

使用定价组件:

<app-pricing ngModelGroup="multiCurrency"></app-pricing>

定价组件类:

export class PricingComponent implements OnInit, AfterViewChecked {
  @ContentChild(NgModelGroup)
  private _group: NgModelGroup;

  @ViewChild('pricingType')
  private _type: NgModel;

  @ViewChild('pricingAmount')
  private _amount: NgModel;

  private _registered = false;

  ngAfterViewChecked() {
    if (!this._registered && this._group.control != null) {
      this._group.control.registerControl('type', this._type.control);
      this._group.control.registerControl('amount', this._amount.control);
      this._registered = true;
    }
  }
}

定价组件模板:

  <div>
    <md-select #pricingType="ngModel" name="type">
      <md-option></md-option>
    </md-select>
    <md-input-container>
      <input #pricingAmount="ngModel" name="amount" mdInput>
    </md-input-container>
  </div>

来源:http://plnkr.co/edit/xJr1ZZBkSz3TuT43Tpwm?p=preview