Angular 2 CheckboxControlValueAccessor实现

时间:2017-05-31 14:05:12

标签: angular

当我们实现CheckboxControlValueAccessor时,我们得到以下错误:

类型具有私有属性'_renderer'

的单独声明

代码:

export class NHCheckbox implements CheckboxControlValueAccessor {

_align = "right";
_label = "";                    // Label
_required = false;
_tooltip: string = null;


constructor(
    private _renderer: Renderer,
    private _elementRef: ElementRef
) {

}

CheckboxControlValueAccessor类:

export declare class CheckboxControlValueAccessor implements ControlValueAccessor {
private _renderer;
private _elementRef;
onChange: (_: any) => void;
onTouched: () => void;
constructor(_renderer: Renderer, _elementRef: ElementRef);
writeValue(value: any): void;
registerOnChange(fn: (_: any) => {}): void;
registerOnTouched(fn: () => {}): void;
setDisabledState(isDisabled: boolean): void;

}

我们做错了什么?

Angular Version:4.1.3 打字稿:2.3.4

1 个答案:

答案 0 :(得分:4)

当我在Angular 2+中需要一个复选框组件时,做同样的事情似乎很直观。当你可以从一个复选框开始时,为什么要从一般控制开始,对吧?在花了太多时间之后,我决定放弃并改用ControlValueAccessor

正如您在this plnkr中所看到的,复选框组件可以这样写:

import { Component, /*Input,*/ Renderer, ElementRef, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'my-checkbox',
  template: `
      <div class="checkbox-container">
        <input type="checkbox" id="{{ controlID }}"
              [checked]="checked" (change)="onChange($event)" />
        <label for="{{ controlID }}"></label>
      </div>
    `,
  styles: [`
        .checkbox-container {
            background-color: #ddd;
            width: 20px;
            height: 20px;
            position: relative;
        }
    `, `
        .checkbox-container input[type="checkbox"] {
            visibility: hidden;
        }
    `, `
        .checkbox-container label {
          width: 18px;
          height: 18px;
          position: absolute;
          top: 1px;
          left: 1px;
          background-color: white;
        }
    `,`
        .checkbox-container label:before {
            content: '';
            width: 16px;
            height: 8px;
            border: 4px solid #000;
            position: absolute;
            border-top: none;
            border-right: none;
            transform: rotate(-50deg);
            top: 1px;
            left: 1px;
            opacity: 0;
        }
    `, `
        .checkbox-container input[type="checkbox"]:checked + label:before {
            opacity: 1;
        }
    `],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CheckboxComponent),
      multi: true
    }
  ]
})
export class CheckboxComponent implements ControlValueAccessor {
  static idCounter: Number = 0;
  controlID: String;
  //@Input() checked: Boolean;
  checked: Boolean;

  constructor(private renderer: Renderer, private elementRef: ElementRef) {
    this.controlID = "myCheckbox" + CheckboxComponent.idCounter++;
  }

  propagateChange = (_: any) => { };
  onTouchedCallback: () => {};

  writeValue(value: any) {
    if ((value !== undefined) && (value !== null)) {
      this.checked = value;
    }
  }

  registerOnChange(fn: any) {
    this.propagateChange = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouchedCallback = fn;
  };

  onChange(event) {
    this.checked = event.target.checked;
    this.propagateChange(event.target.checked);
  }
}

可以像这样使用:

<form #form="ngForm" (ngSubmit)="submit(form.value)">
  <div>
    <h2>Checkbox Demo Using {{ framework }}</h2>
  </div>
  <div>
    <my-checkbox name="b1" [(ngModel)]="b1"></my-checkbox>
    <my-checkbox name="b2" [(ngModel)]="b2"></my-checkbox>
    <my-checkbox name="b3" [(ngModel)]="b3"></my-checkbox>
  </div>
</form>

<pre>{{ form.value | json }}</pre>

注意:

  1. controlID必须是唯一的,可以使用静态计数器显示。
  2. 我决定不让checked成为一个 输入()变量,因为您可以使用外部ngModel变量完成相同的操作。
  3. 只读和其他功能 为简单起见省略。