Reputation: 429
I have an Angular Application, I want to implement and Autocomplete Dropdown in my Application, I checked the sample code from Angular material, its not perfect, and does allow users to type even after they select an option. and it does not validate. I want something like this (https://bootsnipp.com/snippets/0Bn1j ) and my options should be as Key Value, Key should be CountryID and Value should be CountryName I am new to This any help would be appreciated. I saw an example here (https://stackblitz.com/edit/angular-autocomplete-validation?file=src%2Fapp%2Fautocomplete-validation-example.html) but its options is string my option is coming from database table with CountryId and CountryName
component.ts:
function autocompleteStringValidator(validOptions: Array<string>): ValidatorFn {
console.log(validOptions);
return (control: AbstractControl): { [key: string]: any } | null => {
if (validOptions.indexOf(control.value) !== -1) {
return null /* valid option selected */
}
return { 'invalidAutocompleteString': { value: control.value } }
}
}
export class TasksformComponent implements OnInit {
public phoneLabelOptions: any[] = [];
public filteredPhoneLabelOptions: Observable<any[]>
public phoneLabelAutocompleteControl = new FormControl('',
{ validators: [autocompleteStringValidator(this.phoneLabelOptions), Validators.required] })
public validation_msgs = {
'contactAutocompleteControl': [
{ type: 'invalidAutocompleteObject', message: 'Contact name not recognized. Click one of the autocomplete options.' },
{ type: 'required', message: 'Contact is required.' }
],
'phoneLabelAutocompleteControl': [
{ type: 'invalidAutocompleteString', message: 'Phone label not recognized. Click one of the autocomplete options.' },
{ type: 'required', message: 'Phone label is required.' }
]
}
private _filterPhoneLabels(label: any): any[] {
console.log('---cling----');
console.log(label);
if (label === '') {
return this.phoneLabelOptions.slice()
}
const filterValue = label.toLowerCase()
return this.phoneLabelOptions.filter(option => option.Name.toLowerCase().includes(filterValue))
}
ngOnInit(): void{
this.filteredPhoneLabelOptions = this.phoneLabelAutocompleteControl.valueChanges.pipe(
startWith(''),
map((value) => {
console.log('---ite here----');
console.log(value);
return this._filterPhoneLabels(value)
})
)
let lookupTablename: string;
console.log('------'+this.categoryID);
this.selected = this.categoryID;
this.lookupService.getLookupByTableAlias((lookupTablename = 'category')).subscribe(
(icategory: any) => {
this.category = icategory;
//console.log(icategory);
icategory.forEach((item)=>{
this.phoneLabelOptions.push({ID:item.ID, Name:item.Name});
});
console.log(this.phoneLabelOptions);
},
error => {
const res = this.dialogService.ErrorDialog('Server Error', 'Sorry, the system is unavailable at the moment.', 'Close', 'Try Again');
res.afterClosed().subscribe(dialogResult => {
if (dialogResult) {
this.callNext(4000);
}
});
}
);
}
component.html:
<mat-form-field>
<input type="text" placeholder="Phone label" aria-label="Phone label" matInput
[formControl]="phoneLabelAutocompleteControl" [matAutocomplete]="autoPhoneLabel">
<mat-autocomplete #autoPhoneLabel="matAutocomplete">
<mat-option *ngFor="let label of filteredPhoneLabelOptions | async" [value]="label.ID">
{{label.Name}}
</mat-option>
</mat-autocomplete>
<mat-error *ngFor="let validation of validation_msgs.phoneLabelAutocompleteControl">
<div *ngIf="phoneLabelAutocompleteControl.hasError(validation.type)">
{{validation.message}}
</div>
</mat-error>
</mat-form-field>
Upvotes: 2
Views: 3683
Reputation: 2292
I beleive you can work with mat-auto-complete.
All you have to do is to provide the values in the array as well.
public contactOptions: Contact[] = [
{id: 1, name: 'Elton John', value:'elton'},
{id: 2, name: 'Elvis Presley', value:'Elvis'},
{id: 3, name: 'Paul McCartney', value:'Paul'}
]
And the value can be set to either string or number from the interface.
export interface Contact {
name: string;
value:string;
id: number;
}
Alright, now we are halfway done. Once the dropdown value is selected, you will be able to get the name. With that name, you can just add find() method in your contactOptions
array and fetch the respected value and you are done.
let result:any = this.contactOptions.find(res=> res.name === selectedValue);
let value = result.value; //===> value: '' from object
let id = result.id
Upvotes: 1