首页 文章

Angular 2:'Control Value Accessor'关于嵌套元素

提问于
浏览
0

我这里有'control value accessor'班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

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

    providers: [
      {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => PricingComponent),
        multi: true
      }
    ]
    
  • 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

相关问题