Topic: Multiple mdb-auto-completer in a single form
JeroenVunderink premium asked 4 years ago
Expected behavior I expect that since I use different functions for the two mdb-auto-completer they work completely independent from each other
Actual behavior Putting each mdb-auto-completer separtely on a page they work. Putting 2 beneath each other it doesn't. Only the first mdb-auto-completer works properly and and after select it fills in the seconds one as well with the first one value and clog errors starting with: ERROR TypeError: this.listenFunc is not a function at MdbAutoCompleterDirective._hide (ng-uikit-pro-standard.js:12277) at SafeSubscriber._next (ng-uikit-pro-standard.js:12311)
Resources (screenshots, code snippets etc.)
The TS File:
import { Component, OnInit } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { startWith, switchMap, debounceTime, map } from 'rxjs/operators';
@Component({
selector: 'app-autocomplete',
templateUrl: './autocomplete.component.html',
styleUrls: ['./autocomplete.component.scss']
})
export class AutocompleteComponent implements OnInit {
searchText = new Subject();
results: Observable<string[]>;
data: any = [
'red',
'green',
'blue',
'cyan',
'magenta',
'yellow',
'black',
];
searchText2 = new Subject();
results2: Observable<string[]>;
data2: any = [
'audi',
'citroen',
'crysler',
'fiat',
'ford',
'peugeot',
'volvo'
];
ngOnInit() {
this.results = this.searchText.pipe(
startWith(''),
map((value: string) => this.filter(value))
);
this.results2 = this.searchText2.pipe(
startWith(''),
map((value: string) => this.filter2(value))
);
}
filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.data.filter((item: string) => item.toLowerCase().includes(filterValue));
}
filter2(value: string): string[] {
const filterValue = value.toLowerCase();
return this.data2.filter((item: string) => item.toLowerCase().includes(filterValue));
}
}
The HTML File:
<p>autocomplete works!</p>
<div class="md-form">
<input
type="text"
class="completer-input form-control mdb-autocomplete"
[ngModel]="searchText | async"
(ngModelChange)="searchText.next($event)"
[mdbAutoCompleter]="auto"
placeholder="Choose your color"
/>
<mdb-auto-completer #auto="mdbAutoCompleter" textNoResults="I have found no results :(">
<mdb-option *ngFor="let option of results | async" [value]="option">
{{ option }}
</mdb-option>
</mdb-auto-completer>
</div>
<div class="md-form">
<input
type="text"
class="completer-input form-control mdb-autocomplete"
[ngModel]="searchText2 | async"
(ngModelChange)="searchText2.next($event)"
[mdbAutoCompleter]="auto"
placeholder="Choose your brand"
/>
<mdb-auto-completer #auto="mdbAutoCompleter" textNoResults="I have found no results :(">
<mdb-option *ngFor="let car of results2 | async" [value]="car">
{{ option }}
</mdb-option>
</mdb-auto-completer>
</div>
JeroenVunderink premium answered 4 years ago
Thank you so much. I didn't exactly know/understand how the binding worked.
For other users that encounter the same issue I have put the updated code below that works.
The TS file:
import { Component, OnInit } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { startWith, map } from 'rxjs/operators';
@Component({
selector: 'app-autocomplete',
templateUrl: './autocomplete.component.html',
styleUrls: ['./autocomplete.component.scss']
})
export class AutocompleteComponent implements OnInit {
searchText = new Subject();
results: Observable<string[]>;
data: any = [
'red',
'green',
'blue',
'cyan',
'magenta',
'yellow',
'black',
];
searchText2 = new Subject();
results2: Observable<string[]>;
data2: any = [
'audi',
'citroen',
'crysler',
'fiat',
'ford',
'peugeot',
'volvo'
];
ngOnInit() {
this.results = this.searchText.pipe(
startWith(''),
map((value: string) => this.filter(value))
);
this.results2 = this.searchText2.pipe(
startWith(''),
map((value: string) => this.filter2(value))
);
}
filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.data.filter((item: string) => item.toLowerCase().includes(filterValue));
}
filter2(value: string): string[] {
const filterValue = value.toLowerCase();
return this.data2.filter((item: string) => item.toLowerCase().includes(filterValue));
}
}
The HTML file:
<p>autocomplete works!</p>
<div class="md-form">
<input
type="text"
class="completer-input form-control mdb-autocomplete"
[ngModel]="searchText | async"
(ngModelChange)="searchText.next($event)"
[mdbAutoCompleter]="color"
placeholder="Choose your color"
/>
<mdb-auto-completer #color="mdbAutoCompleter" textNoResults="I have found no results :(">
<mdb-option *ngFor="let option of results | async" [value]="option">
{{ option }}
</mdb-option>
</mdb-auto-completer>
</div>
<div class="md-form">
<input
type="text"
class="completer-input form-control mdb-autocomplete"
[ngModel]="searchText2 | async"
(ngModelChange)="searchText2.next($event)"
[mdbAutoCompleter]="car"
placeholder="Choose your brand"
/>
<mdb-auto-completer #car="mdbAutoCompleter" textNoResults="I have found no results :(">
<mdb-option *ngFor="let car of results2 | async" [value]="car">
{{ car }}
</mdb-option>
</mdb-auto-completer>
</div>
Arkadiusz Idzikowski staff answered 4 years ago
That's because you used the same id #auto
for both components. This value should be unique. When you set new, unique value for second autocomplete, you also need to update it here: [mdbAutoCompleter]="auto2"
metalor-it pro commented 3 years ago
Hello, How to manage a dynamic form using a static # ? imagin I have the Autocompleter #supplier for the first article. I if I hadd a second article at runtime the Autocompleter is also #supplier. Is there a way to make it dynamic ? Thank you
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Resolved
- ForumUser: Premium
- Premium support: Yes
- Technology: MDB Angular
- MDB Version: 9.1.0
- Device: MacAir
- Browser: Chrome
- OS: MacOS
- Provided sample code: No
- Provided link: No