diff --git a/src/combo-box.component.ts b/src/combo-box.component.ts index eb5386c..7664094 100644 --- a/src/combo-box.component.ts +++ b/src/combo-box.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit, Input, Output, EventEmitter, forwardRef, ViewChild} from '@angular/core'; import {Observable, Subscription} from 'rxjs/Rx'; -import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; +import {AbstractControl, ControlValueAccessor, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator} from '@angular/forms'; @Component({ moduleId: 'ng2-combobox', @@ -12,12 +12,12 @@ import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; (keydown)="onKeyDown($event)" (blur)="onFieldBlur($event)" (focus)="onFieldFocus()"> - +
- +
ComboBoxComponent), multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ComboBoxComponent), + multi: true }] }) -export class ComboBoxComponent implements ControlValueAccessor, OnInit { +export class ComboBoxComponent implements ControlValueAccessor, OnInit, Validator { @Input() displayField: string; @@ -142,6 +147,7 @@ export class ComboBoxComponent implements ControlValueAccessor, OnInit { hideList: boolean = true; data: any[]; + valid: boolean = false; private _loading: boolean = false; private _listDataSubscription: Subscription; @@ -160,6 +166,10 @@ export class ComboBoxComponent implements ControlValueAccessor, OnInit { private propagateChange = (_: any) => { }; + // Validator props + private propagateValidate = () => { + }; + constructor() { } @@ -187,9 +197,15 @@ export class ComboBoxComponent implements ControlValueAccessor, OnInit { }); } else { let data = value; + if(!data) { + data = []; + } this.data = this._initialData = data; this.loading = false; } + + // During initialisation, the validation was not being triggered after setting the list data. + this.propagateValidate(); } @Input() @@ -437,29 +453,22 @@ export class ComboBoxComponent implements ControlValueAccessor, OnInit { this.propagateChange(this.getValueValue(val)); } - private searchValueObject(value: any): any { - if (false === value instanceof Object && this.valueField && this._initialData) { - this._initialData.forEach((item) => { - if (value === this.getValueValue(item)) { - value = item; - } - }); - } - return value; + private searchByDisplayValue(displayValue: any): any { + return this._initialData.find(item => this.getDisplayValue(item) === displayValue); } onTriggerClick() { this._input.nativeElement.focus(); } + // Implement ControlValueAccessor interface + writeValue(value: any): void { - value = this.searchValueObject(value); - if (value instanceof Object && this.getDisplayValue(value)) { - this.currVal = this.getDisplayValue(value); - } else { - this._tmpVal = value; - } + this.currVal = this.getDisplayValue(value); + this._tmpVal = this.getValueValue(value); + + this.propagateTouch(); this.onInitValue.emit(value); } @@ -471,4 +480,28 @@ export class ComboBoxComponent implements ControlValueAccessor, OnInit { registerOnTouched(fn: any): void { this.propagateTouch = fn; } + + // Implement Validator interface + validate(c: AbstractControl): { [key: string]: any; } { + + if (!this.remote && this._initialData && this._initialData.length > 0) { + + if(!this.currVal || !this.currVal.trim()) { + return {'empty_input': 'Input value is empty'}; + } else { + let isValid = !! this.searchByDisplayValue(this.currVal); + if(!isValid) { + return {'input_no_match': `Cannot match the input value '${this.currVal}' to any of the provided data`}; + } + } + } + + // TODO implement validation for remote data + + return null; + } + + registerOnValidatorChange(fn: () => void): void { + this.propagateValidate = fn; + } }