import { AfterViewInit, Component, EventEmitter, forwardRef, Input, Output, OnDestroy, ViewChild } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { NouisliderComponent } from 'ng2-nouislider'; import { Observable } from 'rxjs/Observable'; import { Observer } from 'rxjs/Observer'; import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged'; export interface SliderPips { mode: string; values: number[]; density: number; stepped?: boolean; } export interface SliderProps { min: number; max: number; step?: number; pips?: SliderPips; valueUnit?: string; } @Component({ selector: 'slider-wrapper', templateUrl: './slider-wrapper.component.html', styleUrls: ['./slider-wrapper.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SliderWrapperComponent), multi: true } ] }) export class SliderWrapperComponent implements AfterViewInit, ControlValueAccessor, OnDestroy { @ViewChild(NouisliderComponent) slider: NouisliderComponent; @Input() label: string; @Input() tooltip: string; @Input() min: number; @Input() max: number; @Input() step: number; @Input() pips: SliderPips; @Input() valueUnit: string; @Output() onChange = new EventEmitter(); public value: number; private changeObserver$: Observer; private changeDebounceTime: number = 300; ngAfterViewInit(): void { if (this.pips) { this.slider.slider.pips(this.pips); } // Hide tooltips and show them when dragging slider handle this.slider.slider.target.querySelector('.noUi-tooltip').style.display = 'none'; this.slider.slider.on('start', function() { this.target.querySelector('.noUi-tooltip').style.display = 'block'; }); this.slider.slider.on('end', function() { this.target.querySelector('.noUi-tooltip').style.display = 'none'; }); } ngOnDestroy() { if (this.changeObserver$) { this.changeObserver$.complete(); } } writeValue(value: number): void { this.value = value || this.min; } registerOnChange(fn: any): void { this.propagateChange = fn; } registerOnTouched() {} onSliderChange(value: number): void { if (!this.changeObserver$) { Observable.create(observer => { this.changeObserver$ = observer; }).debounceTime(this.changeDebounceTime) .distinctUntilChanged() .subscribe(this.propagateChange); return; // No change event on first change as the value is just being set } this.changeObserver$.next(value); } private propagateChange: any = () => {}; }