import {Component, ElementRef, Input, Output, EventEmitter, OnChanges, SimpleChange} from '@angular/core'; import {ISVocabulariesService} from './ISVocabularies.service'; import {RefineFieldResultsService} from '../../services/refineFieldResults.service'; import{EnvProperties} from '../../utils/properties/env-properties'; //Usage example // @Component({ selector: 'static-autocomplete', host: { '(document:click)': 'handleClick($event)', }, template: `
{{showItem(item)}}
` }) export class StaticAutoCompleteComponent implements OnChanges{ @Input() placeHolderMessage = "Search for entries"; @Input() title = "Autocomplete"; @Output() addItem = new EventEmitter(); // when selected list changes update parent component @Output() selectedValueChanged = new EventEmitter(); // when changed a method for filtering will be called @Output() updateValueLabel = new EventEmitter(); //when the value is id sends an event to update the value (for meta tags) @Output() listUpdated = new EventEmitter(); // when changed a method for filtering will be called @Input() public list = []; // the entries resulted after filtering function @Input() public filtered = []; // the entries resulted after filtering function @Input() public selected = []; // the entries selected from user @Input() public keywordlimit = 3; // the minimum length of keyword @Input() public showSelected = true; // the minimum length of keyword @Input() public multipleSelections:boolean = true; @Input() public allowDuplicates:boolean = false; @Input() public selectedValue:string = ''; @Input() public vocabularyId:string ; @Input() public fieldName:string ; @Input() public fieldValues; @Input() public entityName:string ; @Input() public fieldId:string ; @Input() properties:EnvProperties; @Input() public keyword = ''; @Input() public type = 'search' //search, result, context, project @Input() id; public warningMessage = ""; public infoMessage = ""; public showLoading:boolean = false; public tries = 0; public showInput = true; public sub; public done = false; public results = 0; public focus:boolean = false; public currentFieldId: string ; constructor ( private _vocabulariesService: ISVocabulariesService,private _refineService: RefineFieldResultsService, private myElement: ElementRef) { this.currentFieldId=this.fieldId; } ngOnDestroy(){ if(this.sub){ this.sub.unsubscribe(); } this._vocabulariesService.clearSubscriptions(); } ngOnChanges(changes: {[propKey: string]: SimpleChange}) { if(this.currentFieldId!=this.fieldId){ //this is going to be called when this.currentFieldId=this.fieldId; this.initialize(); } } private initialize(){ this.showInput = true; if(this.list == undefined || this.list.length == 0){ this.showLoading = true; if(this.vocabularyId){ // this.list = this._vocabulariesService.getVocabularyByType(this.vocabularyId, this.entityName); // this.afterListFetchedActions(); this.sub = this._vocabulariesService.getVocabularyByType(this.vocabularyId, this.entityName, this.properties).subscribe( data => { if(data) { this.list = (this.vocabularyId == "type" && this.entityName == "result" && data.length == 2) ? data[0].concat(data[1]) : data; this.afterListFetchedActions(); } else { this.handleError("Error getting vocabulary with id: "+this.vocabularyId+" for "+this.entityName); this.warningMessage = "Error, couldn't fetch results..."; this.showLoading = false; this.afterListFetchedActions(); } } ); }else if(this.fieldName && this.entityName){ if(this.fieldValues) { this.list = this._refineService.parse(this.fieldValues, this.fieldName); this.afterListFetchedActions(); } else { this.sub = this._refineService.getRefineFieldResultsByFieldName(this.fieldName, this.entityName, this.properties).subscribe( data => { this.list = data; this.afterListFetchedActions(); }, err => { //console.log(err); this.handleError("Error getting results for refine field: " + this.fieldName + " for " + this.entityName, err); this.warningMessage = "Error, couldn't fetch results..."; this.showLoading = false; this.afterListFetchedActions(); } ); } }else{ this.showLoading = false; } }else{ this.afterListFetchedActions(); } } public updateList(list){ // used in claim context autocomplete this.list = list; this.afterListFetchedActions() } private afterListFetchedActions(){ this.showLoading = false; this.getSelectedNameFromGivenId(); this.listUpdated.emit({ value: this.list }); if(this.list == null || this.list.length == 0 ){ return; } this.done = true; if(this.keyword != ""){ this.filter(); } } filter() { this.focus = true; if(this.done){ this.infoMessage = ""; this.filtered = []; if(this.keyword == ""){ var cut = 10; if(this.list.length < 5){ cut = this.list.length; } this.results = this.list.length; this.filtered =this.list.slice(0, cut); this.tries = 0; this.warningMessage = ""; // } else if(this.keyword && this.keyword.length < this.keywordlimit){ // this.tries++; // if(this.tries == this.keywordlimit -1 ){ // this.warningMessage = "Type at least " + this.keywordlimit + " characters"; // this.tries = 0; // } }else{ this.tries = 0; this.warningMessage = ""; this.filtered = this.list.filter(function(el){ return el.label.toLowerCase().indexOf(this.keyword.toLowerCase()) > -1; }.bind(this)); var cut = 10; if(this.filtered .length < 5){ cut = this.list.length; } this.results = this.filtered.length; this.filtered =this.filtered.slice(0, cut); } } } remove(item:any){ var index:number =this.checkIfExists(item,this.selected); if (index > -1) { this.selected.splice(index, 1); } if(!this.multipleSelections && this.selected.length == 0 ){ this.showInput = true; this.selectedValue = ""; this.selectedValueChanged.emit({ value: this.selectedValue }); this.updateValueLabel.emit({ value:"" }); } } select(item:any){ // console.log("select"+this.selected.length + item.id + " "+ item.label); if(this.multipleSelections){ var index:number =this.checkIfExists(item,this.selected); if (index > -1 && !this.allowDuplicates) { this.keyword = ""; this.filtered.splice(0, this.filtered.length); return; } else{ this.selected.push(item); this.keyword = ""; this.filtered.splice(0, this.filtered.length); this.addItem.emit({ value: item }); } }else{ this.selected.splice(0, this.selected.length); this.selected.push(item); this.filtered.splice(0, this.filtered.length); this.keyword = ""; this.showInput = false; this.selectedValue = item.id; this.selectedValueChanged.emit({ value: this.selectedValue }); this.updateValueLabel.emit({ value:this.showItem(item) }); } } private checkIfExists(item:any,list):number{ if(item.concept && item.concept.id ){ for (var _i = 0; _i < list.length; _i++) { let itemInList = list[_i]; if(item.concept.id == itemInList.concept.id){ return _i; } } }else if(item.id){ for (var _i = 0; _i < list.length; _i++) { let itemInList = list[_i]; if(item.id == itemInList.id){ return _i; } } } return -1; } showItem(item:any):string{ if (item.name){ //search return item.name; }else if( item.concept && item.concept.label){ //context return item.concept.label; }else if (item.label){ //simple return item.label; } } truncate(str:string, size:number):string{ if(str == null){return "";} return (str.length > size)?str.substr(0,size)+'...':str; } private getSelectedNameFromGivenId(){ if(!this.selectedValue){ return; } if(this.list == null || this.list.length == 0 ){ this.selected.push({label: this.selectedValue, id: this.selectedValue}); this.showInput = false; this.updateValueLabel.emit({ value:this.showItem(this.selected[0]) }); return; } this.showInput = true; for( var i = 0; i < this.list.length; i++){ if(this.list[i].id == this.selectedValue){ this.selectedValue = this.list[i].label; this.selected.push(this.list[i]); this.showInput = false; this.updateValueLabel.emit({ value:this.showItem(this.list[i]) }); return; } } } handleClick(event){ var clickedComponent = event.target; var inside = false; do { if (clickedComponent === this.myElement.nativeElement) { inside = true; } clickedComponent = clickedComponent.parentNode; } while (clickedComponent); if(!inside){ this.focus =false; this.filtered.splice(0, this.filtered.length); } } private handleError(message: string, error = null) { console.error("Static Autocomplete (component): "+message, error); } }