// 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'] // }));