[ACS-10332] Search: Editable Combobox Without Autocomplete Does Not D… (#11310)

This commit is contained in:
dominikiwanekhyland
2025-10-30 14:29:05 +01:00
committed by GitHub
parent a4f5cfc964
commit 4feba2f304
5 changed files with 48 additions and 12 deletions
@@ -33,7 +33,6 @@
</mat-chip-grid> </mat-chip-grid>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)" id="adf-search-chip-autocomplete" <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)" id="adf-search-chip-autocomplete"
(optionActivated)="activeAnyOption = true" (closed)="activeAnyOption = false"> (optionActivated)="activeAnyOption = true" (closed)="activeAnyOption = false">
<ng-container *ngIf="optionInput.value.length > 0">
<mat-option <mat-option
*ngFor="let option of filteredOptions" *ngFor="let option of filteredOptions"
[value]="option" [value]="option"
@@ -46,6 +45,5 @@
> >
{{ option.fullPath || option.value }} {{ option.fullPath || option.value }}
</mat-option> </mat-option>
</ng-container>
</mat-autocomplete> </mat-autocomplete>
</mat-form-field> </mat-form-field>
@@ -340,5 +340,17 @@ describe('SearchChipAutocompleteInputComponent', () => {
component.selectedOptions = [option]; component.selectedOptions = [option];
expect(component.isOptionSelected(option)).toBeTrue(); expect(component.isOptionSelected(option)).toBeTrue();
}); });
it('should clear filteredOptions after input is cleared', async () => {
enterNewInputValue('option');
await fixture.whenStable();
fixture.detectChanges();
expect(component.filteredOptions.length).toBe(component.autocompleteOptions.length);
enterNewInputValue('');
await fixture.whenStable();
fixture.detectChanges();
expect(component.filteredOptions.length).toBe(component.autocompleteOptions.length);
});
}); });
}); });
@@ -33,7 +33,7 @@ import { ENTER } from '@angular/cdk/keycodes';
import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatChipInputEvent, MatChipsModule } from '@angular/material/chips'; import { MatChipInputEvent, MatChipsModule } from '@angular/material/chips';
import { EMPTY, Observable, timer } from 'rxjs'; import { Observable, timer } from 'rxjs';
import { debounce, startWith, tap } from 'rxjs/operators'; import { debounce, startWith, tap } from 'rxjs/operators';
import { AutocompleteOption } from '../../models/autocomplete-option.interface'; import { AutocompleteOption } from '../../models/autocomplete-option.interface';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@@ -77,7 +77,7 @@ export class SearchChipAutocompleteInputComponent implements OnInit, OnChanges {
@Input() @Input()
filter = (options: AutocompleteOption[], value: string): AutocompleteOption[] => { filter = (options: AutocompleteOption[], value: string): AutocompleteOption[] => {
const filterValue = value.toLowerCase(); const filterValue = value.toLowerCase();
return options.filter((option) => option.value.toLowerCase().includes(filterValue)).slice(0, 15); return options?.filter((option) => option.value.toLowerCase().includes(filterValue)).slice(0, 15) ?? [];
}; };
@Output() @Output()
@@ -104,11 +104,11 @@ export class SearchChipAutocompleteInputComponent implements OnInit, OnChanges {
.pipe( .pipe(
startWith(''), startWith(''),
tap(() => (this.activeAnyOption = false)), tap(() => (this.activeAnyOption = false)),
debounce((value: string) => (value ? timer(300) : EMPTY)), debounce(() => timer(300)),
takeUntilDestroyed(this.destroyRef) takeUntilDestroyed(this.destroyRef)
) )
.subscribe((value: string) => { .subscribe((value: string) => {
this.filteredOptions = value ? this.filter(this.autocompleteOptions, value) : []; this.filteredOptions = this.filter(this.autocompleteOptions, value);
this.inputChanged.emit(value); this.inputChanged.emit(value);
}); });
this.onReset$?.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => this.reset()); this.onReset$?.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => this.reset());
@@ -24,6 +24,7 @@ import { AutocompleteField } from '../../models/autocomplete-option.interface';
import { TagService } from '../../../tag/services/tag.service'; import { TagService } from '../../../tag/services/tag.service';
import { SitesService } from '../../../common/services/sites.service'; import { SitesService } from '../../../common/services/sites.service';
import { SitePaging } from '@alfresco/js-api'; import { SitePaging } from '@alfresco/js-api';
import { CategoryService } from '../../../category';
describe('SearchFilterAutocompleteChipsComponent', () => { describe('SearchFilterAutocompleteChipsComponent', () => {
let component: SearchFilterAutocompleteChipsComponent; let component: SearchFilterAutocompleteChipsComponent;
@@ -211,4 +212,31 @@ describe('SearchFilterAutocompleteChipsComponent', () => {
done(); done();
}); });
}); });
it('should still call sitesService.getSites when input is empty for LOCATION field', () => {
component.settings.field = AutocompleteField.LOCATION;
const getSitesSpy = spyOn(sitesService, 'getSites').and.returnValue(
of({
list: { entries: [], pagination: {} }
})
);
component.onInputChange('');
expect(getSitesSpy).toHaveBeenCalled();
});
it('should still call categoryService.searchCategories when input is empty for CATEGORIES field', () => {
component.settings.field = AutocompleteField.CATEGORIES;
const categoryService = TestBed.inject(CategoryService);
const searchSpy = spyOn(categoryService, 'searchCategories').and.returnValue(
of({
list: { entries: [], pagination: {} }
})
);
component.onInputChange('');
expect(searchSpy).toHaveBeenCalledWith('', 0, 15);
});
}); });
@@ -122,12 +122,10 @@ export class SearchFilterAutocompleteChipsComponent implements SearchWidget, OnI
} }
onInputChange(value: string) { onInputChange(value: string) {
if (value) { if (this.settings.field === AutocompleteField.CATEGORIES) {
if (this.settings.field === AutocompleteField.CATEGORIES) { this.searchForExistingCategories(value);
this.searchForExistingCategories(value); } else if (this.settings.field === AutocompleteField.LOCATION) {
} else if (this.settings.field === AutocompleteField.LOCATION) { this.populateSitesOptions();
this.populateSitesOptions();
}
} }
} }