summaryrefslogtreecommitdiffstats
path: root/src/angular/autocomplete
diff options
context:
space:
mode:
Diffstat (limited to 'src/angular/autocomplete')
-rw-r--r--src/angular/autocomplete/autocomplete.component.html.ts14
-rw-r--r--src/angular/autocomplete/autocomplete.component.ts114
-rw-r--r--src/angular/autocomplete/autocomplete.module.ts23
-rw-r--r--src/angular/autocomplete/autocomplete.pipe.ts16
4 files changed, 167 insertions, 0 deletions
diff --git a/src/angular/autocomplete/autocomplete.component.html.ts b/src/angular/autocomplete/autocomplete.component.html.ts
new file mode 100644
index 0000000..5df7352
--- /dev/null
+++ b/src/angular/autocomplete/autocomplete.component.html.ts
@@ -0,0 +1,14 @@
+export default `
+<div class="sdc-autocomplete-container" [ngClass]="{'results-shown': autoCompleteResults.length}">
+ <sdc-filter-bar
+ [placeholder]="placeholder"
+ [label]="label"
+ [searchQuery]="searchQuery"
+ (searchQueryChange)="onSearchQueryChanged($event)">
+ </sdc-filter-bar>
+ <ul class="autocomplete-results" [@displayResultsAnimation]="autoCompleteResults.length ?'true':'false'">
+ <li *ngFor="let item of autoCompleteResults"
+ (click)="onItemSelected(item)">{{item.value}}</li>
+ </ul>
+</div>
+`;
diff --git a/src/angular/autocomplete/autocomplete.component.ts b/src/angular/autocomplete/autocomplete.component.ts
new file mode 100644
index 0000000..5570eff
--- /dev/null
+++ b/src/angular/autocomplete/autocomplete.component.ts
@@ -0,0 +1,114 @@
+import { OnInit, animate, Component, EventEmitter, Input, Output, state, style, transition, trigger } from '@angular/core';
+import { FilterBarComponent } from "../filterbar/filter-bar.component";
+import { URLSearchParams, Http } from "@angular/http";
+import { AutocompletePipe } from "./autocomplete.pipe";
+import template from "./autocomplete.component.html";
+import 'rxjs/add/operator/map';
+
+export interface IDataSchema {
+ key: string;
+ value: string;
+}
+
+@Component({
+ selector: 'sdc-autocomplete',
+ template: template,
+ animations: [
+ trigger('displayResultsAnimation', [
+ state('true', style({
+ height: '*',
+ opacity: 1
+ })),
+ state('false', style({
+ height: 0,
+ opacity: 0
+ })),
+ transition('* => *', animate('200ms'))
+ ]),
+ ],
+ providers: [AutocompletePipe]
+})
+export class SearchWithAutoCompleteComponent implements OnInit {
+ @Input() public data: any[] = [];
+ @Input() public dataSchema: IDataSchema;
+ @Input() public dataUrl: string;
+ @Input() public label: string;
+ @Input() public placeholder: string;
+ @Output() public itemSelected: EventEmitter<any> = new EventEmitter<any>();
+
+ private searchQuery: string;
+ private complexData: any[] = [];
+ private autoCompleteResults: any[] = [];
+ private isItemSelected: boolean = false;
+
+ public constructor(private http: Http, private autocompletePipe: AutocompletePipe) {
+ }
+
+ public ngOnInit(): void {
+ if (this.data) {
+ this.handleLocalData();
+ }
+ this.searchQuery = "";
+ }
+
+ private handleLocalData = (): void => {
+ // Convert the data (simple | complex) to unified complex data with key value.
+ // In case user supplied dataSchema, this is complex data
+ if (!this.dataSchema) {
+ this.convertSimpleData();
+ } else {
+ this.convertComplexData();
+ }
+ }
+
+ private convertSimpleData = (): void => {
+ this.complexData = [];
+ this.data.forEach((item: any) => {
+ this.complexData.push({key: item, value: item});
+ });
+ }
+
+ private convertComplexData = (): void => {
+ this.complexData = [];
+ this.data.forEach((item: any) => {
+ this.complexData.push({key: item[this.dataSchema.key], value: item[this.dataSchema.value]});
+ });
+ }
+
+ private onItemSelected = (selectedItem: IDataSchema): void => {
+ this.searchQuery = selectedItem.value;
+ this.isItemSelected = true;
+ this.autoCompleteResults = [];
+ this.itemSelected.emit(selectedItem.key);
+ }
+
+ private onSearchQueryChanged = (searchText: string): void => {
+ if (searchText !== this.searchQuery) {
+ this.searchQuery = searchText;
+ if (!this.searchQuery) {
+ this.onClearSearch();
+ } else {
+ if (this.dataUrl) {
+ const params: URLSearchParams = new URLSearchParams();
+ params.set('searchQuery', this.searchQuery);
+ this.http.get(this.dataUrl, {search: params})
+ .map((response) => {
+ this.data = response.json();
+ this.handleLocalData();
+ this.autoCompleteResults = this.complexData;
+ }).subscribe();
+ } else {
+ this.autoCompleteResults = this.autocompletePipe.transform(this.complexData, this.searchQuery);
+ }
+ }
+ this.isItemSelected = false;
+ }
+ }
+
+ private onClearSearch = (): void => {
+ this.autoCompleteResults = [];
+ if (this.isItemSelected) {
+ this.itemSelected.emit();
+ }
+ }
+}
diff --git a/src/angular/autocomplete/autocomplete.module.ts b/src/angular/autocomplete/autocomplete.module.ts
new file mode 100644
index 0000000..1bead47
--- /dev/null
+++ b/src/angular/autocomplete/autocomplete.module.ts
@@ -0,0 +1,23 @@
+import { NgModule } from "@angular/core";
+import { SearchWithAutoCompleteComponent } from "./autocomplete.component";
+import { CommonModule } from "@angular/common";
+import { FilterBarModule } from "../filterbar/filter-bar.module";
+import { AutocompletePipe } from "./autocomplete.pipe";
+import { HttpModule } from '@angular/http';
+
+@NgModule({
+ declarations: [
+ SearchWithAutoCompleteComponent,
+ AutocompletePipe
+ ],
+ imports: [
+ FilterBarModule,
+ CommonModule,
+ HttpModule
+ ],
+ exports: [
+ SearchWithAutoCompleteComponent
+ ],
+})
+export class AutoCompleteModule {
+}
diff --git a/src/angular/autocomplete/autocomplete.pipe.ts b/src/angular/autocomplete/autocomplete.pipe.ts
new file mode 100644
index 0000000..bee24ab
--- /dev/null
+++ b/src/angular/autocomplete/autocomplete.pipe.ts
@@ -0,0 +1,16 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { IDataSchema } from './autocomplete.component';
+
+@Pipe ({
+ name: 'AutocompletePipe',
+})
+export class AutocompletePipe implements PipeTransform {
+ public transform(data: IDataSchema[], text: string) {
+ if (!text || !text.length) {
+ return data;
+ }
+ return data.filter((item: IDataSchema) => {
+ return item.value.toLowerCase().indexOf(text.toLowerCase()) > -1;
+ });
+ }
+}