Need assistance in implementing a search box into an angular drop down and I don’t know how to quite get it to function correctly based on what code I have so far for the html and typescript.
Can anybody please help me to implement a search filter with the select component in my application?
I’m using a search component that can be inserted into other components using a selector in the typescript called ‘lf-material-search’.
Here is the HTML for the search component
<ng-template #legacyInput>
<form class="input-group add-border"
[formGroup]="form"
[class.btn-search-input]="hasButtonStyles"
[class.flex-nowrap]="hasButtonStyles"
[class.search-input-loading]="isLoading"
[class.search-input-focused]="hasFocus()">
<span *ngIf="hasGroupAddon"
class="input-group-addon">
<img src="/assets/images/payhoa/other/search.svg"/>
</span>
<span *ngIf="!hasGroupAddon"
class="search-input-container">
<span *ngIf="isLoading"
class="d-inline-flex p-relative p-0 loading"></span>
</span>
<input #searchInput
formControlName="search"
class="form-control"
type="text"
aria-label="Material search input"
[placeholder]="defaultPlaceholder"/>
<span *ngIf="hasGroupAddon"
class="input-group-addon"
(click)="clearSearch()">
<img src="/assets/images/app/icons/icon_close.svg"/>
</span>
</form>
</ng-template>
<ng-container *ngIf="newInput; else legacyInput">
<ng-container [formGroup]="form">
<mat-form-field appearance="outline"
class="payhoa-field payhoa-search w-100">
<mat-icon matPrefix>search</mat-icon>
<input matInput
type="text"
aria-label="Search and find results"
[formControlName]="'search'"
[placeholder]="defaultPlaceholder">
</mat-form-field>
</ng-container>
</ng-container>
This is where I added the selector from the search component into the dropdown that is in another component.
<ul *ngIf="options" class="dropdown-menu" style="width: 100%;">
<!-- *<lf-material-search #searchInput
(updated)="toggleAccount($event)"></lf-material-search>-->
<lf-material-search #searchInput
(updated)="toggleAccount(1, false)"></lf-material-search>*
<ng-container *ngIf="options.assets &&
options.assets.length">
<li class="dropdown-item group-header">
Assets
</li>
<ng-template [ngForOf]="options.assets" let-asset
ngFor>
<li (click)="this.toggleAccount(asset)"
[class.selected]="selection.isSelected(asset)"
class="dropdown-item">
<a>{{asset.display}}</a>
</li>
</ng-template>
</ng-container>
</ul>
but I still can’t get any results when I do a search in the application. What am I missing or need to pass from the typescript below to the lf-material-search to get this to work?
Typescript
@UntilDestroy()
@Component({
selector: 'report-filter-account-register-selector',
templateUrl: './account-register-selector.component.html',
styleUrls: ['./account-register-selector.component.scss'],
})
export class AccountRegisterSelectorComponent implements OnInit
{
jwt: JwtLegFiClaims;
expanded: boolean = false;
@Input()
public container: FilterContainerComponent;
public selection: SelectionModel<AccountRegisterFilterOption> = new
SelectionModel<AccountRegisterFilterOption>(true);
public options: AccountRegisterFilters = null;
constructor(
private _reportsService: ReportsService,
private _growler: GrowlerService,
) {
}
ngOnInit() {
this.container.register(this);
this.jwt = LegFiJwtService.read();
this._reportsService.getAccountRegisterFilters()
.pipe(untilDestroyed(this)).subscribe(
(options) => {
this.options = options;
this.container.notifyReady(this);
},
() => {
this._growler.error(
);
},
);
}
toggleAccount(account, children = false) {
this.selection.toggle(account);
if (children) {
const doToggleOn =
!this.selection.isSelected(account.children[0]);
account.children.forEach((child) => {
if (doToggleOn) {
this.selection.select(child);
} else {
this.selection.deselect(child);
}
});
}
}
}
When I type in the word ‘Burnt’ it doesn’t filter for that nor anything else
If anyone could help me I would definitely appreciate it.
In general implement a search when depend of a formControl you have an observable that is the control.valueChange transform (using switchMap or map)
Then you use pipeAsync to get the list
<input [formControl]="control">
<ul>
@for(value of list$|async;track $index)
{
<li>{{value}}</li>
}
</ul>
If you have, e.g. a
export const List = ['one', 'two', 'three', 'four', 'five', 'six'];
You use
list$: Observable<string[]> = this.control.valueChanges.pipe(
startWith(''),
map((value: any) => {
if (!value) return List;
value = value.toUpperCase();
return List.filter((x: string) => x.toUpperCase().indexOf(value) >= 0)
})
);
If you call to an API when change the value you use switchMap
list$: Observable<string[]> = this.control.valueChanges.pipe(
startWith(''),
debounceTime(100), //<--this is to not call to api so many times
switchMap((value: any) => {
if (!value) return this.dataService.getAll();
return this.dataService.getAllContains(value)
})
);
In the stackblitz I use rxjs operator of
in the service, generally it’s used one kind of this.httpClient.get(...)