自定义组件上的NgModel

时间:2017-03-08 15:28:40

标签: angular typescript

我有一个简单的组件,我在表单中包含这样的内容:

<app-slider [min]="field.min" [max]="field.max" [value]="field.min"></app-slider>

该组件如下:

HTML:

<input #mySlider
       class="slider"
       type="text"
       name="slider"
       data-provide="slider"
       data-slider-min="1"
       data-slider-max="3"
       [attr.data-slider-min]="min"
       [attr.data-slider-max]="max"
       data-slider-step="1"
       [attr.data-slider-value]="value"
       data-slider-tooltip="show"/>

TS:

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

declare var $ : any;

@Component({
    selector: 'app-slider',
    templateUrl: './slider.component.html',
    styleUrls: ['./slider.component.css']
})
export class SliderComponent{
    @ViewChild('mySlider') slider: any; // can be ElementRef;
    @Input() min: number;
    @Input() max: number;
    @Input() value: number;

    constructor() { }

    ngAfterViewInit() {
        // slider is available
        $(this.slider.nativeElement).slider();
        let value = $(this.slider.nativeElement).attr("data-slider-value");
        $(this.slider.nativeElement).slider('setValue', value);
    }
}

我想在我的组件上添加NgModel,以便我可以获得并更改其值:

<app-slider [min]="field.min" [max]="field.max" [value]="field.min" [(ngModel)]="currentValue"></app-slider>

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:3)

试试这个:

initval-1

使用<app-slider [min]="field.min" [max]="field.max" [(value)]="currentValue"></app-slider>

更改currentValue的值
changeCurrentValue

答案 1 :(得分:3)

前言:看起来你使用像jquery ui滑块这样但有点不同。在我不得不假设的地方,我使用了它的api。

我想通过实现ControlValueAccessor来实现您想要做的事情,以使组件被ng识别为表单控件,或者换句话说自定义表单控件。不确定语法是否与最新的ng方法是最新的,但我过去看起来如下:

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

declare var $: any;

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

@Component({
    selector: 'app-slider',
    templateUrl: './slider.component.html',
    styleUrls: ['./slider.component.css'],
    providers: [
        SLIDER_VALUE_ACCESSOR
    ]
})
export class SliderComponent implements ControlValueAccessor {
    @ViewChild('mySlider') slider: any; // can be ElementRef;
    @Input() min: number;
    @Input() max: number;

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

    constructor() { }

    ngAfterViewInit() {
        // slider is available
        $(this.slider.nativeElement).slider();
    }

    onChange() {
        this.propagateChange($(this.slider.nativeElement).attr("data-slider-value"););
    }

    /**
     * Write a new value to the element.
     */
    writeValue(value: any): void {
        $(this.slider.nativeElement).slider('setValue', value);
    }

    /**
     * Set the function to be called when the control receives a change event.
     */
    registerOnChange(fn: any): void {
        this.propagateChange = fn;
    }

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

    /**
     * This function is called when the control status changes to or from "DISABLED".
     * Depending on the value, it will enable or disable the appropriate DOM element.
     *
     * @param isDisabled
     */
    setDisabledState?(isDisabled: boolean): void {
        // it would look like this if jQuery UI slider was used
        $(this.slider.nativeElement).slider(isDisabled ? "disable" : "enable");
    }
}

模板如:

<input #mySlider
    class="slider"
    type="text"
    name="slider"
    data-provide="slider"
    data-slider-min="1"
    data-slider-max="3"
    [attr.data-slider-min]="min"
    [attr.data-slider-max]="max"
    data-slider-step="1"
    data-slider-tooltip="show"
    (change)="onChange" /> <!-- change event as in jQuery UI slider  -->

和用法:

<app-slider [min]="field.min" [max]="field.max" [(ngModel)]="currentValue"></app-slider>

并且currentValue必须使用min值初始化才能正常工作,因为它似乎在示例中起作用。