Topic: Multiple mdb-auto-completer in a single form

JeroenVunderink premium asked 3 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 3 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 3 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



Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Resolved

Specification of the issue

  • 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