Skip to content

Instantly share code, notes, and snippets.

@NetanelBasal
Created July 15, 2017 20:27
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save NetanelBasal/8f5dc9fe717929e75e344bf59a163c97 to your computer and use it in GitHub Desktop.
Save NetanelBasal/8f5dc9fe717929e75e344bf59a163c97 to your computer and use it in GitHub Desktop.
import { Directive, ElementRef, forwardRef, Input, Renderer2 } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { fromEvent } from 'rxjs/observable/fromEvent';
import { merge } from 'rxjs/observable/merge';
import { timer } from 'rxjs/observable/timer';
import { Subscription } from 'rxjs/Subscription';
export const DEFAULT_VALUE_ACCESSOR : any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgControlOptionsDirective),
multi: true
};
@Directive({
selector: 'input[type=text][formControlName][ngControlOptions],input[type=text][formControl][ngControlOptions]',
providers: [DEFAULT_VALUE_ACCESSOR]
})
export class NgControlOptionsDirective implements ControlValueAccessor {
events : Subscription;
onChange;
onTouched;
registerOnChange( fn : any ) : void {
this.onChange = fn;
}
registerOnTouched( fn : any ) : void {
this.onTouched = fn;
}
constructor( private renderer : Renderer2, private element : ElementRef ) {
}
private _controlOptions = {
updateOn: 'input',
debounce: null
};
@Input() set ngControlOptions( val ) {
this._controlOptions = { ...this._controlOptions, ...val };
}
ngOnInit() {
const events = this._controlOptions.updateOn.split(' ').map(event => fromEvent(this.element.nativeElement, event));
this.events = merge(...events)
.map(( e : Event ) => ( { type: e.type, value: e.target['value'] }))
.debounce(event => {
const debounceValue = this._controlOptions.debounce;
let time = 0;
if( typeof debounceValue === 'number' ) {
time = debounceValue;
} else if( typeof debounceValue === 'object' ) {
time = debounceValue[event.type] ? debounceValue[event.type] : 0;
}
return timer(time);
})
.subscribe(event => {
this.onChange(event.value);
});
// this.events = merge(...events)
// .map(( e : Event ) => ( {type: e.type, value: e.target[ 'value' ]}))
// .let(source => {
// if ( this._controlOptions.debounce ) {
// return source.debounce(event => {
// const time = ...
// return timer(time);
// });
// }
// return source;
// })
// .subscribe(event => {
// this.onChange(event.value);
// });
}
writeValue( value : any ) : void {
const normalizedValue = value == null ? '' : value;
this.renderer.setProperty(this.element.nativeElement, 'value', normalizedValue);
}
setDisabledState( isDisabled : boolean ) : void {
this.renderer.setProperty(this.element.nativeElement, 'disabled', isDisabled);
}
ngOnDestroy() {
this.events.unsubscribe();
}
}
@talamaska
Copy link

talamaska commented Jul 19, 2017

I guess the value of the const time is this._controlOptions.debounce on line 66, the same thing as on line 50 right?

@born2net
Copy link

born2net commented Jul 19, 2017

awesome!

@qetr1ck-op
Copy link

It's freaking marvelous!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment