diff --git a/ui-ngx/src/app/shared/components/string-items-list.component.ts b/ui-ngx/src/app/shared/components/string-items-list.component.ts index a4a8ebd49b..5929bbe924 100644 --- a/ui-ngx/src/app/shared/components/string-items-list.component.ts +++ b/ui-ngx/src/app/shared/components/string-items-list.component.ts @@ -14,7 +14,16 @@ /// limitations under the License. /// -import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; +import { + Component, + DestroyRef, + ElementRef, + forwardRef, + Input, + OnInit, + ViewChild, + ViewEncapsulation +} from '@angular/core'; import { AbstractControl, ControlValueAccessor, @@ -31,6 +40,7 @@ import { Observable, of } from 'rxjs'; import { filter, mergeMap, share, tap } from 'rxjs/operators'; import { MatAutocompleteTrigger } from '@angular/material/autocomplete'; import { isDefined } from '@core/utils'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; export interface StringItemsOption { name: string; @@ -120,6 +130,10 @@ export class StringItemsListComponent implements ControlValueAccessor, OnInit { @Input() fetchOptionsFn: (searchText?: string) => Observable>; + @Input() + @coerceBoolean() + allowUserValue = false; + get itemsControl(): AbstractControl { return this.stringItemsForm.get('items'); } @@ -132,7 +146,8 @@ export class StringItemsListComponent implements ControlValueAccessor, OnInit { private propagateChange: (value: any) => void = () => {}; private dirty = false; - constructor(private fb: FormBuilder) { + constructor(private fb: FormBuilder, + private destroyRef: DestroyRef) { this.stringItemsForm = this.fb.group({ item: [null], items: [null] @@ -151,6 +166,7 @@ export class StringItemsListComponent implements ControlValueAccessor, OnInit { } }), filter((value) => typeof value === 'string'), + tap(name => this.searchText = name), mergeMap(name => this.fetchOptionsFn ? this.fetchOptionsFn(name) : this.fetchValues(name)), share() ); @@ -243,12 +259,20 @@ export class StringItemsListComponent implements ControlValueAccessor, OnInit { private addItem(value: string) { const item = value.trim(); if (item) { - if (this.predefinedValues) { + if (this.predefinedValues && !this.allowUserValue) { const findItems = this.predefinedValues .filter(value => value.name.toLowerCase().includes(item.toLowerCase())); if (findItems.length === 1) { this.add(findItems[0]); } + } else if (isDefined(this.fetchOptionsFn) && !this.allowUserValue) { + this.fetchOptionsFn(item).pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe((findItems) => { + if (findItems.length === 1) { + this.add(findItems[0]); + } + }) } else { this.add({value: item, name: item}); } @@ -272,7 +296,6 @@ export class StringItemsListComponent implements ControlValueAccessor, OnInit { if (!this.predefinedValues?.length) { return of([]); } - this.searchText = searchText; let result = this.predefinedValues; if (searchText && searchText.length) { result = this.predefinedValues.filter(option => option.name.toLowerCase().includes(searchText.toLowerCase()));