将Angular 2组件的绑定委托给嵌套元素

时间:2017-02-16 22:04:40

标签: angular checkbox components custom-controls

这些绑定效果很好:

<input type="checkbox" (click)="foo.bar()" [(ngModel)]="foo.baz">

但是如何将这些绑定委托给组件中的输入

<custom-checkbox>Check me!</custom-checkbox>

...这里是“custom-checkbox.component.html”:

<span class="checkbox-wrap">
  <input type="checkbox" class="checkbox"> <!-- This should have all the bindings -->
  <span class="checkbox-styling"></span>
  <span class="checkbox-label"><ng-content></ng-content></span>
</span>

我已经使用Angular 1几年了,但本周才开始使用Angular 2。我已经阅读了许多文章,例如Custom form controls in Angular,Angular文档,其他有些类似的Stack Overflow问题,以及Angular 2 TypeScript上使用的Material Checkbox但我仍然没有得到它们如何拉下这个。看起来它应该更直接。

这是我需要做的许多自定义UI元素之一,所以我希望这个例子能帮助我理解我所缺少的原则和实现。

我知道我可以使用带有选择器的输入复选框,然后将其换行,但我希望像Angular 2 Material checkbox一样干净。

我基本上都在做同样的事情(Angular 2 Material),但是我们拥有自己的造型,比他们提供的所有选项都简单得多。就像他们说的那样,

  

&LT; MD-复选框&GT;提供与本机&lt; input type =“checkbox”&gt;相同的功能。通过Material Design样式和动画增强。

这就是我想要做的事情。

1 个答案:

答案 0 :(得分:0)

尽管Angular 1的链接功能似乎使整个过程变得更容易,但本文似乎通过内置接口给出了Angular 2 Material正在使用的内容,并提供了一个很好的示例:Angular 2: Connect your custom control to ngModel with Control Value Accessor.

这允许开发团队通过直接绑定到组件来使用我的组件,但是将绑定中继到模板中的复选框(或其他表单元素)。

从网站引用以便于链接中断时的文档持久性:

  

所以不用多说,这是我们的组成部分:

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

const noop = () => {
};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => CustomInputComponent),
    multi: true
};

@Component({
    selector: 'custom-input',
    template: `<div class="form-group">
                    <label><ng-content></ng-content>
                        <input [(ngModel)]="value"
                                class="form-control"
                                (blur)="onBlur()" >
                    </label>
                </div>`,
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CustomInputComponent implements ControlValueAccessor {

    //The internal data model
    private innerValue: any = '';

    //Placeholders for the callbacks which are later providesd
    //by the Control Value Accessor
    private onTouchedCallback: () => void = noop;
    private onChangeCallback: (_: any) => void = noop;

    //get accessor
    get value(): any {
        return this.innerValue;
    };

    //set accessor including call the onchange callback
    set value(v: any) {
        if (v !== this.innerValue) {
            this.innerValue = v;
            this.onChangeCallback(v);
        }
    }

    //Set touched on blur
    onBlur() {
        this.onTouchedCallback();
    }

    //From ControlValueAccessor interface
    writeValue(value: any) {
        if (value !== this.innerValue) {
            this.innerValue = value;
        }
    }

    //From ControlValueAccessor interface
    registerOnChange(fn: any) {
        this.onChangeCallback = fn;
    }

    //From ControlValueAccessor interface
    registerOnTouched(fn: any) {
        this.onTouchedCallback = fn;
    }

}
  

然后我们可以按如下方式使用此自定义控件:

<form>

    <custom-input name="someValue"
                  [(ngModel)]="dataModel">
          Enter data:
    </custom-input>

</form>

感谢Almero Steyn !!