Topic: Autocomplete displayValue and manually set value
Hi,
I'm using the mdbautocomplete with a server side search. When user selects something, i want to keep the UserSelected object, and write the FullName in the field. So i used "displayValue" for that purpose. Template-driven form .html:
<div class="md-form">
<input #userInput="ngModel" type="text" class="completer-input form-control " [(ngModel)]="SearchText" [mdbAutoCompleter]="auto"
placeholder="Nom ou matricule" (focusout)="OnLeave()"/>
<mdb-auto-completer #auto="mdbAutoCompleter" [displayValue]="displayFn" >
<mdb-option *ngFor="let user of userList" [value]="user">
<div class="d-flex flex-column">
<span><strong>{{ user.FullName }}</strong></span>
<span>{{ user.Societe }}</span>
</div>
</mdb-option>
</mdb-auto-completer>
</div>
TS file:
OnLeave() {
if (this.userInput.value === '') {
this.SelectedUser = null;
}
this.SearchText = this.SelectedUser;
}
displayFn(user): string {
return user && user.FullName ? user.FullName : '';
}
ngAfterViewInit(): void {
this.userInput
.valueChanges
.pipe(debounceTime(300), filter(theNewValue => typeof theNewValue === 'string'))
.subscribe(theNewValue => {
this.searchUser(theNewValue);
});
this.userInput
.valueChanges
.pipe(filter(theNewValue => typeof theNewValue !== 'string'))
.subscribe(theNewValue => {
this.SelectedUser = theNewValue;
});
}
With this, i can keep track of the latest selecteduser, and the actual search text. If the user change the search text, but does not select anyone, and leave the text, i would like to put back the name of the previous selected user (as a 'cancel search' would do)
But when i do: this.SearchText = this.SelectedUser; i get [Object object] in the field instead of the actual FullName, (displayValue function is not called)
What am i doing wrong?
Thanks!
Fiducial answered 5 years ago
Hi, Here are the request files with a simple static example: [HTML]:
<div class="md-form">
<input #userInput2="ngModel" type="text" class="completer-input form-control " [(ngModel)]="SearchText" [mdbAutoCompleter]="auto2"
placeholder="Nom ou matricule" (focusout)="OnLeave()"/>
<mdb-auto-completer #auto2="mdbAutoCompleter" [displayValue]="displayFn" >
<mdb-option *ngFor="let user of userList" [value]="user">
<div class="d-flex flex-column">
<span><strong>{{ user.FullName }}</strong></span>
</div>
</mdb-option>
</mdb-auto-completer>
</div>
[TS]
import {AfterViewInit, Component, OnInit, ViewChild} from '@angular/core';
import {debounceTime, filter} from 'rxjs/operators';
@Component({
selector: 'app-test-mdb-autocomplete',
templateUrl: './test-mdb-autocomplete.component.html',
styleUrls: ['./test-mdb-autocomplete.component.css']
})
export class TestMdbAutocompleteComponent implements OnInit,AfterViewInit {
constructor() {
}
userStaticList = [
{FullName: 'Marine', ID: '1'},
{FullName: 'Fred', ID: '2'},
{FullName: 'Marinette', ID: '3'},
{FullName: 'Marilou', ID: '4' }
];
userList = [];
@ViewChild('userInput2') private userInput2;
SearchText = '';
SelectedUser: null;
ngOnInit(): void {
//Render [object Object] instead of user.FullName (Marine) in the search field
//displayFn not called
this.SearchText = this.userStaticList[0];
}
ngAfterViewInit() {
this.userInput2.valueChanges
.pipe(debounceTime(300),
filter(val => typeof val === 'string')
).subscribe(val => {
this.userList = [];
this.userStaticList.forEach(elem => {
if (elem.FullName.toLowerCase().startsWith(val.toString().toLowerCase())) {
this.userList.push(elem);
}
});
}
);
this.userInput2
.valueChanges
.pipe(filter(theNewValue => typeof theNewValue !== 'string'))
.subscribe(theNewValue => {
this.SelectedUser = theNewValue;
});
}
displayFn(user) {
let nameOfUser= (user ? user.FullName : '');
console.log('DisplayFn:'+user);
console.log('DisplayFn returned value:'+nameOfUser);
return nameOfUser;
}
OnLeave() {
if (this.userInput2.value) {
if (this.SelectedUser) {
this.SearchText = this.SelectedUser;
} else {
this.SearchText = '';
}
}else
{
this.SelectedUser=null;
}
}
}
Thanks
Arkadiusz Idzikowski staff answered 5 years ago
In this case SearchText
should be of type string and you try to overwrite it with object here:
this.SearchText = this.userStaticList[0];
and here:
this.SearchText = this.SelectedUser;
In your case it should look like this:
this.SearchText = this.userStaticList[0].FullName;
this.SearchText = this.SelectedUser.FullName;
If you don't use TSLint it is good idea to configure it in your IDE/Code editor, because it will automatically let you know about problems with types.
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- User: Free
- Premium support: No
- Technology: MDB Angular
- MDB Version: 9.0.1
- Device: PC
- Browser: Chromium
- OS: WIndows
- Provided sample code: No
- Provided link: No
Arkadiusz Idzikowski staff commented 5 years ago
Can you prepare a simple example with static data and full html/ts code so we can reproduce that on our end?