Warning, /firebird/firebird-ng/src/app/components/resource-select/resource-select.component.ts is written in an unsupported language. File is not indexed.
0001 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
0002 import {FormControl, ReactiveFormsModule} from '@angular/forms';
0003 import { Observable } from 'rxjs';
0004 import { map, startWith } from 'rxjs/operators';
0005 import {MatFormField} from "@angular/material/form-field";
0006 import {MatAutocomplete, MatAutocompleteTrigger, MatOption} from "@angular/material/autocomplete";
0007 import {AsyncPipe, NgForOf} from "@angular/common";
0008 import {MatTooltip} from "@angular/material/tooltip";
0009 import {MatInput, MatLabel} from "@angular/material/input";
0010
0011
0012 @Component({
0013 selector: 'firebird-resource-select',
0014 standalone: true,
0015 imports: [
0016 MatFormField,
0017 MatAutocompleteTrigger,
0018 MatAutocomplete,
0019 MatOption,
0020 AsyncPipe,
0021 NgForOf,
0022 MatTooltip,
0023 MatInput,
0024 MatLabel,
0025 ReactiveFormsModule
0026 ],
0027 templateUrl: './resource-select.component.html',
0028 styleUrl: './resource-select.component.scss'
0029 })
0030 export class ResourceSelectComponent implements OnInit {
0031
0032 /**
0033 * List of resources to display in autocomplete
0034 */
0035 @Input() options: string[] = [];
0036
0037 /**
0038 * Watermark text of the control
0039 */
0040 @Input() label: string = 'Select value';
0041
0042 /**
0043 * Emitted every time value is changed by selecting or typing in
0044 */
0045 @Output() valueChange = new EventEmitter<string>();
0046
0047 /**
0048 * The main and resulting value of the control
0049 */
0050 public value: FormControl = new FormControl();
0051
0052 /**
0053 * List of filtered options depending on user input
0054 */
0055 public filteredOptions: Observable<string[]> = this.value.valueChanges.pipe(
0056 startWith(''),
0057 map(input=>this.filterOptions(input))
0058 );
0059
0060 ngOnInit(): void {
0061 // Connect value changes with the control output
0062 this.value.valueChanges.subscribe(()=>{
0063 this.valueChange.emit(this.value.value)
0064 });
0065 }
0066
0067 /**
0068 * Filters options depending on what is the value
0069 * @param inputValue
0070 * @private
0071 */
0072 private filterOptions(inputValue: any) {
0073
0074 // options could be undefined
0075 if(!this.options) return [];
0076
0077 // Safeguard the name. inputValue could be string or RemoteResourceOption or whatever...
0078 const name = typeof inputValue === 'string' ? inputValue : (inputValue?.name ?? '');
0079
0080 // Get options containing "name"
0081 let filteredList = name ? this._selectOptions(name) : this.options.slice();
0082
0083 // Explanation of the return: if we have only 1 option, that fully fit the name,
0084 // we probably have it selected already. Which means we want to show everything, so users can select something else
0085 return (filteredList.length == 1 && name === filteredList[0]) ? this.options.slice() : filteredList;
0086 }
0087
0088 /**
0089 * Retrieves the options which .name contains subString.
0090 *
0091 * @param {string} subString - sub string that every option.name is tested by.
0092 * @return {string[]} The filtered remote resource options.
0093 */
0094 private _selectOptions(subString: string): string[] {
0095 const filterValue = subString.toLowerCase();
0096 return this.options.filter(option => option.toLowerCase().includes(filterValue));
0097 }
0098
0099 /**
0100 * Display proper value if value is selected or typed in by user
0101 *
0102 * @param {any | string} input - It is a string (if user is typing) or RemoteResourceOption (if it is selected)
0103 * @return {string} We should return some string instead
0104 */
0105 onDisplayValueChange(input: any | string): string {
0106 let result: string = '';
0107 if (typeof input === 'string') {
0108 result = input;
0109 } else if (input && typeof input.url === 'string') {
0110 result = input.url;
0111 }
0112 return result;
0113 }
0114 }