Topic: How to detect all changes to input value mdb-auto-completer

Arsenii pro asked 4 years ago


Firstly, I need to mention that I use 7.5.4 and I can't upgrade to 8.x since my project is in production and the number of style changes required is overwhelming.

I've created the next mdb-auto-completer shell component I'm going to use in my application (with some debug code included):

import { Component, Input, ViewChild, ElementRef, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { startWith, map } from 'rxjs/operators';
import { MdbAutoCompleterComponent } from 'ng-uikit-pro-standard';

@Component({
  selector: 'app-modal-auto-completer',
  template: `
    <div class="md-form">
      <input #autoCompleteInput
        type="text"
        class="completer-input form-control mdb-autocomplete"
        [ngModel]="autoCompleteValue | async"
        (change)="valueChanged($event)"
        (ngModelChange)="autoCompleteValue.next($event); log($event)"
        [mdbAutoCompleter]="autoCompleter"
        placeholder="{{placeholder}}"
      />
      <mdb-auto-completer #autoCompleter="mdbAutoCompleter" textNoResults="{{emptyResult}}">
        <mdb-option *ngFor="let option of optionList | async" [value]="option">
          {{option}}
        </mdb-option>
      </mdb-auto-completer>
    </div>
  `,
  styles: []
})
export class ModalAutoCompleterComponent implements OnInit {
  @ViewChild("autoCompleter") autoCompleter: MdbAutoCompleterComponent;
  @ViewChild("autoCompleteInput") autoCompleteInput: ElementRef;

  @Input() placeholder: string;
  @Input() emptyResult = "No results found";
  @Input() selector: (search: string) => string[];

  autoCompleteValue = new Subject();
  optionList: Observable<string[]>;

  constructor() { }

  ngOnInit() {
    this.optionList = this.autoCompleteValue.pipe(
      startWith(''),
      map((value: string) => this.selector(value))
    );
  }

  valueChanged(event: any) {
    console.log("Changed", event);
  }

  log(event: any) {
    console.log("Event", event);
    console.log("Value", this.autoCompleter.getSelectedItem());
    console.log("Input value", this.autoCompleteInput.nativeElement.value);
  }
}

So I have an input "selector" function that allows me to reuse the component in different places of my application and still hide all pipes, subjects and object things. I was really surprised that for some reason (ngModelChange) is never triggered for the main workflow with the auto completer, that is, to select some option from the list. Also (change) is never triggered at all. What then is way to detect the change of the input value (originated from any source - selection of an option or from manual input)? Using subscriptions for the case is just nonsense since it's expected that the component should work the same as any ordinary input -> it's passed a pointer to some data -> it changes the data on input changes -> at some point all data is submitted without any manual calls to the auto completer or checking it's value.

Thank you in advance for the reply.


Arsenii pro commented 4 years ago

This one also doesn't trigger on option selection: this.autoCompleteValue.subscribe((item) => { console.log("Item", item); }, (err) => { console.log("Error", err); });


Konrad Stępień staff commented 4 years ago

Hi @Arsenii,

Did you try to use select & selected outputs in your code?

Please visit autocomplete API documentatnion for more info. If you have still a problem, please tell me about that.

Best, Konrad.


Arsenii pro commented 4 years ago

Hi @Konrad Stępień Thank you for your reply!

I figured out how to create event emitter reflecting every change needed for me. But then during testing, I found that when you clear the selected option (press "times" icon), duplication of ngModel update happens, that is, ngModel is updated not once but twice. If you clear the value one more time, ngModel updates 3 times and so on - so there is some cycle-reference and unstable behaviour inside the component. Unfortunately, at this point I realized that I shouldn't use the component at all and added an external ng-select library to my project to accomplish my goal.

Regards, Arsenii



Please insert min. 20 characters.

FREE CONSULTATION

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

Status

Opened

Specification of the issue

  • ForumUser: Pro
  • Premium support: No
  • Technology: MDB Angular
  • MDB Version: 7.5.4
  • Device: PC
  • Browser: Chrome
  • OS: Windows 10 x64
  • Provided sample code: No
  • Provided link: No