ronaldkwandy

auto-complete.component.ts

Aug 16th, 2018
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { Component, ElementRef, Input, OnDestroy, Optional, Self, HostBinding, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
  2. import { NgControl } from '@angular/forms';
  3. import { FocusMonitor } from '@angular/cdk/a11y';
  4. import { coerceBooleanProperty } from '@angular/cdk/coercion';
  5. import { MatFormFieldControl } from '@angular/material';
  6. import { Subject } from 'rxjs';
  7.  
  8. import * as lodash from 'lodash';
  9.  
  10. @Component({
  11.   selector: 'app-auto-complete',
  12.   templateUrl: 'auto-complete.component.html',
  13.   styleUrls: ['./auto-complete.component.scss'],
  14.   encapsulation: ViewEncapsulation.None,
  15.   providers: [{ provide: MatFormFieldControl, useExisting: AutoCompleteComponent }]
  16. })
  17. export class AutoCompleteComponent implements MatFormFieldControl<any>, OnDestroy {
  18.  
  19.   public static nextId = 0;
  20.  
  21.   public stateChanges = new Subject<void>();
  22.   public focused = false;
  23.   public errorState = false;
  24.   public controlType = 'app-auto-complete';
  25.  
  26.   @HostBinding('class.floating')
  27.   @HostBinding('attr.aria-describedby') describedBy = '';
  28.   @HostBinding() id = `app-auto-complete-${AutoCompleteComponent.nextId++}`;
  29.  
  30.   get empty() { return (this.selectedValue === null || this.selectedValue === undefined) && (this.keyword === null || this.keyword === ''); }
  31.   get shouldLabelFloat() { return this.focused || !this.empty; }
  32.  
  33.   private _placeholder: string;
  34.   @Input()
  35.   get placeholder(): string { return this._placeholder; }
  36.   set placeholder(value: string) { this._placeholder = value; this.stateChanges.next(); }
  37.  
  38.   private _required = false;
  39.   @Input()
  40.   get required(): boolean { return this._required; }
  41.   set required(value: boolean) { this._required = coerceBooleanProperty(value); this.stateChanges.next(); }
  42.  
  43.   private _disabled = false;
  44.   @Input()
  45.   get disabled(): boolean { return this._disabled; }
  46.   set disabled(value: boolean) { this._disabled = coerceBooleanProperty(value); this.stateChanges.next(); }
  47.  
  48.   private _items: any[] = [];
  49.   private filteredItems: any[] = [];
  50.   @Input()
  51.   get items() { return this._items; }
  52.   set items(items: Array<any>) { this._items = items; this.setFilteredItems(lodash.cloneDeep(items), this.keyword); }
  53.  
  54.   @Output() public valueChange: EventEmitter<any>;
  55.  
  56.   private _value: any;
  57.   @Input()
  58.   get value(): any { return this._value; }
  59.   set value(value: any) { this._value = value; this.stateChanges.next(); }
  60.  
  61.   private _key: string;
  62.   @Input()
  63.   get key(): string { return this._key; }
  64.   set key(key: string) { this._key = key; }
  65.  
  66.   public keyword: string;
  67.   public selectedValue: any;
  68.   public propagateChange = (_: any) => { /* do nothing */ };
  69.   public propagateTouch = (_: any) => { /* do nothing */ };
  70.  
  71.   constructor(
  72.     private fm: FocusMonitor,
  73.     private elRef: ElementRef,
  74.     @Optional() @Self() public ngControl: NgControl
  75.   ) {
  76.     this.keyword = '';
  77.     this.valueChange = new EventEmitter<any>();
  78.     if (this.ngControl != null) {
  79.       this.ngControl.valueAccessor = this;
  80.     }
  81.     fm.monitor(elRef.nativeElement, true).subscribe(origin => {
  82.       this.focused = !!origin;
  83.       this.stateChanges.next();
  84.     });
  85.     /**
  86.      * To Do : Add Internationalization here!
  87.      */
  88.   }
  89.  
  90.   ngOnDestroy() {
  91.     this.stateChanges.complete();
  92.     this.fm.stopMonitoring(this.elRef.nativeElement);
  93.   }
  94.  
  95.   setDescribedByIds(ids: string[]) {
  96.     this.describedBy = ids.join(' ');
  97.   }
  98.  
  99.   onContainerClick(event: MouseEvent) {
  100.     /**
  101.      * To Do : Write Focus element logic here
  102.      */
  103.   }
  104.  
  105.   public writeValue(value: any): void {
  106.     this.selectedValue = value;
  107.     this.setKeyword(value);
  108.     this.setFilteredItems(this.items, this.keyword);
  109.   }
  110.  
  111.   public registerOnChange(fn: (_: any) => {}): void {
  112.     this.propagateChange = fn;
  113.   }
  114.  
  115.   public registerOnTouched(fn: (_: any) => {}): void {
  116.     this.propagateTouch = fn;
  117.   }
  118.  
  119.   public _onValueChange(value: any): void {
  120.     this.keyword = value;
  121.     this.selectedValue = null;
  122.     this.setFilteredItems(this.items, this.keyword);
  123.     this.propagateChange(this.selectedValue);
  124.     this.valueChange.emit(value);
  125.   }
  126.  
  127.   public setDisabledState(isDisabled: boolean): void {
  128.     this.disabled = isDisabled;
  129.   }
  130.  
  131.   public selectItem(event: any) {
  132.     this.selectedValue = event.option.value;
  133.     this.setKeyword(event.option.value);
  134.     this.propagateChange(event.option.value);
  135.   }
  136.  
  137.   public getItemLabel(item: any): string {
  138.     if (item) {
  139.       if (this.key) {
  140.         return item[this.key];
  141.       } else {
  142.         let localKey = null;
  143.         for (const objKey in item) {
  144.           if (objKey !== 'id' && objKey !== 'version' && objKey !== 'rootId' && objKey !== 'rootVersion') {
  145.             localKey = objKey;
  146.             break;
  147.           }
  148.         }
  149.  
  150.         if (localKey) {
  151.           return item[localKey];
  152.         }
  153.         return 'no-key-defined';
  154.       }
  155.     } else {
  156.       return 'no-key-defined';
  157.     }
  158.   }
  159.  
  160.   private setKeyword(value: any) {
  161.     if (this.key) {
  162.       this.keyword = value[this.key];
  163.     } else {
  164.       let localKey = null;
  165.       for (const objKey in value) {
  166.         if (objKey !== 'id' && objKey !== 'version' && objKey !== 'rootId' && objKey !== 'rootVersion') {
  167.           localKey = objKey;
  168.           break;
  169.         }
  170.       }
  171.  
  172.       if (localKey) {
  173.         this.keyword = value[localKey];
  174.       }
  175.     }
  176.   }
  177.  
  178.   private setFilteredItems(items: any[], keyword: string) {
  179.     this.filteredItems = items.filter(item => {
  180.       if (this.key) {
  181.         return (item[this.key] + '').toLowerCase().indexOf((keyword + '').toLowerCase()) > -1;
  182.       } else {
  183.         let localKey = null;
  184.         for (const objKey in item) {
  185.           if (objKey !== 'id' && objKey !== 'version' && objKey !== 'rootId' && objKey !== 'rootVersion') {
  186.             localKey = objKey;
  187.             break;
  188.           }
  189.         }
  190.  
  191.         if (localKey) {
  192.           return (item[localKey] + '').toLowerCase().indexOf((keyword + '').toLowerCase()) > -1;
  193.         }
  194.         return true;
  195.       }
  196.     });
  197.   }
  198. }
Advertisement
Add Comment
Please, Sign In to add comment