// Angular imports //
import {
Component,
OnInit,
Input,
Inject,
ElementRef,
ViewChild,
HostListener} from '@angular/core';
// import { downgradeComponent } from '@angular/upgrade/static';
// Components //
import * as _ from 'underscore';
// Interfaces //
// Services //
// Directives //
// Pipes //
import { OrderByObjectPipe } from '@fb/common/pipes/orderByObject.pipe';
// Other classes //
import { FbFormBase } from '../fbFormBase';
import * as statics from '@fb/statics';
/**
* Visar en drop-plus som är en dropdown där man kan lägga in nya möjliga värden eller skriva valfri text istället
*
* Syntax:
*
*
* @param model Modell
* @param label Label att visa. Visas inte om tight eller noLabel är satt
* @param disabled Disabled om satt till true
* @param disableReason Används som tooltip vid disabled
* @param noLabel Sätt till true för att dölja label
* @param name Ange om man vill att name-attributet ska sättas
* Övriga param saknas, fyll gärna på
*/
// Todo importera styles enligt wiki /vile
@Component({
selector: 'fb-form-drop-plus',
templateUrl: './fb-form-drop-plus.component.html'
})
export class FbFormDropPlusComponent extends FbFormBase implements OnInit {
showList: boolean;
insideResultList: boolean;
filteredList: fb.DropPlus[];
showAddNew: boolean;
uniqName: string;
@Input() placeholder: string;
@Input() key: string;
@Input() name: string;
private list: fb.List;
@ViewChild('resultList') private resultList: ElementRef;
constructor(
private elementRef: ElementRef,
private orderByObjectPipe: OrderByObjectPipe,
@Inject('DropPlusService') private dropPlusService: fb.IDropPlusService
) {
super();
}
ngOnInit(): void {
super.ngOnInit();
this.list = this.dropPlusService.get(this.key);
this.list.$promise.then(() => {
this.filterList();
});
this.showList = false;
this.uniqName = statics.Guid.new(); // Todo spelling uniqueName - not uniqName /vile
if (this.resultList && this.resultList.nativeElement) {
this.resultList
.nativeElement
.setAttribute('fb-selectable-rows', ''); // Todo fb-selectable-rows should not work here?! fbKeySelectListItem istället /vile
this.resultList
.nativeElement
.setAttribute('key-nav-on-el', '#' + this.uniqName);
}
if (!this.name) {
this.name = statics.Guid.new();
this.name = this.name ? this.name.replace(/ /g, '-').toLowerCase() : '';
}
}
onModelValueUpdate(value: string): void {
this.filterList();
this.highlightIndex(0);
this.showAddNew = this.isNew();
this.updateModel(value);
}
private isNew(): boolean {
return this.model && !!this.model.value
&& !_.find(this.filteredList, (item: fb.DropPlus) => item.Vaerde.value === this.model.value);
}
private highlightIndex(index: number): void {
const listEl: JQuery = $(this.elementRef.nativeElement).find('.fb-selectable-row');
listEl.removeClass('fb-highlight');
if (listEl.length > 1) {
listEl.slice(index, index + 1).addClass('fb-highlight');
} else if (listEl.length === 1) {
listEl.addClass('fb-highlight');
}
}
private filterList(): void {
if (!this.model || !this.model.value || this.model.value === '') {
this.filteredList = _.filter(this.list, () => true);
} else {
this.filteredList = _.filter(this.list, (item: fb.DropPlus) => {
if (this.model && this.model.value) {
return item.Vaerde.value.toLowerCase().indexOf(this.model.value.toLowerCase()) > -1;
}
return false;
});
}
this.filteredList = this.orderByObjectPipe.transform(this.filteredList, 'Vaerde.value', false, true);
}
onKeyDown(event: KeyboardEvent): void {
const key: string = event.code || null;
if (key && (key.toLowerCase() === 'tab' || key.toLowerCase() === 'enter')) {
this.blurList(true);
}
}
@HostListener('focusout')
private blurList(forced?: boolean): void {
if (forced || !this.insideResultList) {
$(this.elementRef.nativeElement).find('.fb-form-control').blur();
this.showList = false;
}
if (forced) {
this.insideResultList = false;
}
}
focus(): void {
$(this.elementRef.nativeElement).find('input').select();
this.filteredList = _.filter(this.list, () => true);
this.filteredList = this.orderByObjectPipe.transform(this.filteredList, 'Vaerde.value', false, true);
const selected: fb.DropPlus = _.find(this.filteredList, item => item.Vaerde.value === this.model.value);
if (selected) {
this.highlightIndex(this.filteredList.indexOf(selected));
}
this.showList = true;
}
select(item: fb.DropPlus): void {
this.blurList(true);
this.filterList();
this.updateModel(item.Vaerde.value);
}
add(): void {
const finnsRedan: fb.DropPlus = _.find(this.list, item => item.Vaerde.value === this.model.value);
if (!finnsRedan) {
const dropPlus: fb.DropPlus = new fb.DropPlus({
Vaerde: this.model.value,
DropPlusTyp: this.key
});
const res: fb.DropPlus = this.dropPlusService.add(dropPlus);
this.filterList();
this.blurList(true);
res.$promise.then(() => {
this.filterList();
this.showAddNew = this.isNew();
});
}
$(this.elementRef.nativeElement).find('input').blur();
}
delete(dropPlus: fb.DropPlus): void {
const res: fb.ResourceBase = this.dropPlusService.remove(dropPlus);
res.$promise.then(() => {
this.showAddNew = this.isNew();
this.filterList();
if (dropPlus.Vaerde.value === this.model.value) {
this.model.setValue(null);
}
});
}
}
// Angular downgrade ////
// angular.module('fasit')
// .directive('fbFormDropPlus',
// downgradeComponent({
// component: FbFormDropPlusComponent,
// inputs: ['noLabel', 'placeholder', 'key', 'name', 'label', 'model', 'disabled', 'disableReason']
// }));