diff --git a/projects/ngx-dadata/src/lib/dadata-config.ts b/projects/ngx-dadata/src/lib/dadata-config.ts index 6141003..0d81f1a 100644 --- a/projects/ngx-dadata/src/lib/dadata-config.ts +++ b/projects/ngx-dadata/src/lib/dadata-config.ts @@ -1,6 +1,6 @@ import {DadataType} from './ngx-dadata.service'; -export interface Locations { +export interface Location { country?: string; country_iso_code?: string; region?: string; @@ -21,6 +21,15 @@ export interface Locations { street_fias_id?: string; } +export interface Bound { + value: 'country' | 'region' | 'city' | 'street' | 'settlement' | 'area' | 'house'; +} + +export interface Bounds { + fromBound?: Bound; + toBound?: Bound; +} + export interface DadataConfig { apiKey: string; type?: DadataType; @@ -29,11 +38,9 @@ export interface DadataConfig { width?: 'auto' | string; minWidth?: '0' | string; partyAddress?: 'city' | 'full'; - locations?: Locations[]; - restrict_value?: boolean; - hint?: boolean; - bounds?: string; - constraints?: any; + locations?: Location[]; + locationsBoost?: Location[]; + bounds?: Bounds; } export const DadataConfigDefault: DadataConfig = { diff --git a/projects/ngx-dadata/src/lib/ngx-dadata.component.html b/projects/ngx-dadata/src/lib/ngx-dadata.component.html index 40f4ec8..f0b6e9f 100644 --- a/projects/ngx-dadata/src/lib/ngx-dadata.component.html +++ b/projects/ngx-dadata/src/lib/ngx-dadata.component.html @@ -1,7 +1,7 @@
- + (keyup.Enter)="onEnter($event)" spellcheck="false" [(ngModel)]="value" autocomplete="off" />
diff --git a/projects/ngx-dadata/src/lib/ngx-dadata.component.ts b/projects/ngx-dadata/src/lib/ngx-dadata.component.ts index c71eb19..fc675c3 100644 --- a/projects/ngx-dadata/src/lib/ngx-dadata.component.ts +++ b/projects/ngx-dadata/src/lib/ngx-dadata.component.ts @@ -39,6 +39,12 @@ export function createDaDataValidator(value) { }; } +/** + * Autocomplete IDs need to be unique across components, so this counter exists outside of + * the component definition. + */ +let uniqueDadataIdCounter = 0; + @Component({ selector: 'ngx-dadata', templateUrl: './ngx-dadata.component.html', @@ -54,6 +60,8 @@ export class NgxDadataComponent implements OnInit, ControlValueAccessor, OnChang private v: any = ''; currentFocus = -1; + opened = false; + data: DadataSuggestion[] = []; @Input() config: DadataConfig = DadataConfigDefault; @@ -73,12 +81,18 @@ export class NgxDadataComponent implements OnInit, ControlValueAccessor, OnChang private inputString$ = new Subject(); + /** Unique ID to be used by autocomplete trigger's "aria-owns" property. */ + id = `ngx-dadata-${uniqueDadataIdCounter++}`; + // onSuggestionSelected = (value: string) => {}; onTouched = () => {}; propagateChange: any = () => {}; validateFn: any = () => {}; - constructor(private dataService: NgxDadataService, private r: Renderer2) { + constructor( + private dataService: NgxDadataService, + private r: Renderer2, + private elRef: ElementRef) { } get value(): any { @@ -101,15 +115,19 @@ export class NgxDadataComponent implements OnInit, ControlValueAccessor, OnChang this.inputString$.pipe( debounce(() => timer(this.config.delay ? this.config.delay : 500)), ).subscribe(x => { - this.dataService.getData(x, this.type, this.limit, this.locations).subscribe((y: DadataResponse) => { + this.dataService.getData(x, this.type, this.config) + .subscribe((y: DadataResponse) => { this.data = y.suggestions; + if (this.data.length) { + this.opened = true; + } }); }); } ngOnChanges(changes: SimpleChanges) { if (changes.value) { - + // console.log('ngOnChanges'); } } @@ -119,23 +137,27 @@ export class NgxDadataComponent implements OnInit, ControlValueAccessor, OnChang } onClick(e: MouseEvent, item: DadataSuggestion) { - // e.preventDefault(); this.inputValue.nativeElement.value = item.value; this.propagateChange(item.value); this.inputValue.nativeElement.focus(); this.selectedSuggestion = item; this.data = []; this.currentFocus = -1; - - // this.writeValue(item.value); + this.opened = false; this.selected.emit(item); // this.selectedData.emit(item.data); // this.selectedString.emit(item.value); } - @HostListener('document:click') - onOutsideClick() { - this.data = []; + @HostListener('document:click', ['$event']) + onOutsideClick($event: MouseEvent) { + if (!this.opened) { + return; + } + if (!this.elRef.nativeElement.contains($event.target)) { + this.data = []; + this.opened = false; + } } onArrowDown() { @@ -158,13 +180,12 @@ export class NgxDadataComponent implements OnInit, ControlValueAccessor, OnChang this.setFocus(this.currentFocus); } - onEnter() { + onEnter(event: KeyboardEvent) { this.selectedSuggestion = this.data[this.currentFocus]; this.inputValue.nativeElement.value = this.selectedSuggestion.value; this.data = []; this.currentFocus = -1; this.propagateChange(this.selectedSuggestion.value); - // this.writeValue(this.selectedSuggestion.value); this.selected.emit(this.selectedSuggestion); // this.selectedData.emit(this.selectedSuggestion.data); // this.selectedString.emit(this.selectedSuggestion.value); @@ -185,8 +206,10 @@ export class NgxDadataComponent implements OnInit, ControlValueAccessor, OnChang writeValue(value: any): void { if (value !== undefined) { this.v = value; + } else { + this.v = ''; } - // this.onSuggestionSelected(value); + this.r.setProperty(this.inputValue.nativeElement, 'innerHTML', this.v); } /** diff --git a/projects/ngx-dadata/src/lib/ngx-dadata.service.ts b/projects/ngx-dadata/src/lib/ngx-dadata.service.ts index b5fccfd..ed4760c 100644 --- a/projects/ngx-dadata/src/lib/ngx-dadata.service.ts +++ b/projects/ngx-dadata/src/lib/ngx-dadata.service.ts @@ -2,7 +2,7 @@ import {Injectable} from '@angular/core'; import {HttpClient, HttpHeaders} from '@angular/common/http'; import {Observable} from 'rxjs'; import {DadataResponse} from './models/dadata-response'; -import {Locations} from './dadata-config'; +import {Bounds, DadataConfig, Location} from './dadata-config'; export enum DadataType { fio = 'fio', @@ -26,7 +26,7 @@ export class NgxDadataService { } // tslint:disable-next-line:max-line-length - getData(value: string, type: DadataType = DadataType.address, count: number = 10, locations: Locations[] = null): Observable { + getData(value: string, type: DadataType = DadataType.address, config: DadataConfig): Observable { const httpOptions = { headers: new HttpHeaders({ Accept: 'application/json', @@ -34,7 +34,15 @@ export class NgxDadataService { Authorization: 'Token ' + this.apiKey, }) }; - const body = Object.assign({query: value, count, locations}); + const body = Object.assign( + {}, + {query: value}, + {count: config?.limit}, + {location: config?.locations}, + {location_bust: config?.locationsBoost}, + {from_bound: config?.bounds?.fromBound}, + {to_bound: config?.bounds?.toBound} + ); return this.http.post('https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/' + type, body, httpOptions); } }