NyeSass
NyeSass

Reputation: 393

ngbTypeahead not calling on change

I am working on creating a Custom Form Control with a Typeahead input field in Angular. I want to call the _onChange function whenever the input changes. However, when I log the _onChange function, I see that it is never called, even though I'm making changes in the input field. Here is my TS file:

import { Component, EventEmitter, forwardRef, Input, Output, ViewChild } from '@angular/core';
    import { AbstractControl, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
    import { NgbTypeahead } from '@ng-bootstrap/ng-bootstrap';
    import { debounceTime, distinctUntilChanged, filter, map, merge, Observable, Subject } from 'rxjs';
    @Component({
      selector: 'app-typeahead-input',
      templateUrl: './typeahead-input.component.html',
      styleUrl: './typeahead-input.component.scss',
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          multi: true,
          useExisting: forwardRef(() => TypeaheadInputComponent),
        },
      ],
    })
    export class TypeaheadInputComponent implements ControlValueAccessor {
      @Input() placeholder: string;
      @Input() dataSource: any[];
      @Input() formatter: (item: any) => string;
      @Input() abstractControl: AbstractControl<any, any>;
      @Input() selectOnExact: boolean;
      @Input() editable: boolean;
    
      @ViewChild('instance', { static: true }) instance: NgbTypeahead;
      focus$ = new Subject<string>();
      click$ = new Subject<string>();
    
      search: (text$: Observable<string>) => Observable<any[]> = (text$: Observable<string>) => {
        const debouncedText$ = text$.pipe(debounceTime(200), distinctUntilChanged());
        const clicksWithClosedPopup$ = this.click$.pipe(filter(() => !this.instance.isPopupOpen()));
        const inputFocus$ = this.focus$;
    
        return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
          map(term =>
            term === ''
              ? this.dataSource
              : this.dataSource
                  .filter(
                    (item: any) =>
                      this.formatter(item)
                        .toLowerCase()
                        .indexOf((term as string).toLowerCase()) > -1
                  )
                  .slice(0, 10)
          )
        );
      };
      _value: any;
      _onChange = value => {};
    
      _onTouched = () => {};
    
      registerOnChange(fn: any): void {
        this._onChange = value => {
          console.log('Current value: ' + this._value);
          fn(value);
        };
      }
    
      registerOnTouched(fn: any): void {
        this._onTouched = fn;
      }
    
      writeValue(obj: any): void {
        console.log(obj);
        this._value = obj;
      }
    }

and my HTML file:

<input
  type="text"
  class="form-control"
  id="formControlName"
  [value]="_value"
  (change)="_onChange(_value)"
  [placeholder]="placeholder"
  [ngbTypeahead]="search"
  [inputFormatter]="formatter"
  [resultFormatter]="formatter"
  #instance="ngbTypeahead"
  (focus)="focus$.next($any($event).target.value)"
  (click)="click$.next($any($event).target.value)"
  [class.is-invalid]="abstractControl.invalid && (abstractControl.dirty || abstractControl.touched)"
  [class.is-valid]="abstractControl.valid"
  [editable]="editable"
  [selectOnExact]="selectOnExact" />
<div class="invalid-feedback" *ngIf="abstractControl.invalid && (abstractControl.dirty || abstractControl.touched)">
  <span *ngIf="abstractControl.errors">{{ placeholder }} muss gesetzt sein.</span>
</div>

Upvotes: 0

Views: 75

Answers (0)

Related Questions