0

I'm trying to follow the Mat Chips documentation here; however Instead of hardcoding the values, I'm trying to connect it thru my firestore database via angularfire.

firestore database:

enter image description here

however I'm kinda lost to the part wherein how to connect it properly. TS Component doesn't show any error, however whenever I load the HTML component, I get this error

enter image description here [enter image description here]

here's my code if you could help find what's the problem here:

HTML:
    <mat-form-field class="form-date" appearance="standard">
      <mat-label>Plumbers</mat-label>
        <mat-chip-list #chipList aria-label="Plumber selection">
            <mat-chip
               *ngFor="let plumber of plumbers"
               (removed)="remove(plumber)">
                {{plumber}}
                <button matChipRemove>
                <mat-icon>cancel</mat-icon>
                </button>
                </mat-chip>
                  <input
                    placeholder="Add Plumber..."
                    #plumberInput
                    [formControl]="plumberCtrl"
                    [matAutocomplete]="auto"
                    [matChipInputFor]="chipList"
                    [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
                    (matChipInputTokenEnd)="add($event)">
                </mat-chip-list>
                <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
                  <mat-option *ngFor="let plumber of filteredPlumbers | async" [value]="plumber">
                    {{plumber}}
                 </mat-option>
                </mat-autocomplete>
       </mat-form-field>

Service TS

import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument} from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs/Observable';
import {map } from 'rxjs/operators';

import { plumberModel } from '../models/plumberModel';

@Injectable({
  providedIn: 'root'
})
export class CustomerService {
  plumberCollection: AngularFirestoreCollection<plumberModel>;
  plumbers: Observable<plumberModel[]>;

 constructor(
    public angularFireStore: AngularFirestore

  ) 
  {}

 getPlumbers() {
    this.plumberCollection = this.angularFireStore.collection('plumber');
    this.plumbers = this.plumberCollection.valueChanges();
    return this.plumbers
  }
}

Model

export class plumberModel {
    plumberName: string;
}

Component TS

import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { CustomerService } from 'src/app/services/customer.service';
import { Customer } from 'src/app/models/customer.model';
import { Observable} from 'rxjs';
import {COMMA, ENTER} from '@angular/cdk/keycodes';
import {FormControl} from '@angular/forms';
import {MatAutocompleteSelectedEvent} from '@angular/material/autocomplete';
import {MatChipInputEvent} from '@angular/material/chips';
import {map, startWith} from 'rxjs/operators';

@Component({
  selector: 'app-update-jo',
  templateUrl: './update-jo.component.html',
  styleUrls: ['./update-jo.component.scss']
})
export class UpdateJOComponent implements OnInit {

     separatorKeysCodes: number[] = [ENTER, COMMA];
     plumberCtrl = new FormControl();
     filteredPlumbers: Observable<plumberModel[]>;
     plumbers: string[] = [];
     allPlumber: plumberModel[];
     @ViewChild('plumberInput') plumberInput: ElementRef<HTMLInputElement>;

  constructor(
    public afs: AngularFirestore,
    private customerService: CustomerService
  ) { 
    this.filteredPlumbers = this.plumberCtrl.valueChanges.pipe(
      startWith(null),
      map((plumber: string | null)=>(plumber ? this._filter(plumber): this.allPlumber.slice()))
    )

  }

add(event: MatChipInputEvent): void {
    const value = (event.value || '').trim();

    if(value) {
      this.plumbers.push(value);
    }

    event.chipInput!.clear();
    this.plumberCtrl.setValue(null);

  }

  remove(plumber:string) {
    const index = this.plumbers.indexOf(plumber);

    if(index >= 0) {
      this.plumbers.slice(index,1);
    }
  }

  selected(event: MatAutocompleteSelectedEvent): void {
    this.plumbers.push(event.option.viewValue);
    this.plumberInput.nativeElement.value = '';
    this.plumberCtrl.setValue(null);
    
  }

ngOnInit(): void {

    this.customerService.getPlumbers().subscribe(plubObs => {
      this.allPlumber = plubObs;
    })
    
  }

}



Carlo A
  • 117
  • 9
  • 1
    Well, "`this.plumberCtrl.value` is not a function" is pretty clear. That's a property, not a function. Did you mean to write `setValue()`? It's in your `add` function. – Chris Hamilton Feb 16 '22 at 20:01
  • Ok but one thing at a time, did you fix the typo I pointed out? Could you update it in your question if so? Then please make a note that you have fixed that error and state whether the other error is still happening. – Chris Hamilton Feb 17 '22 at 05:10
  • yes it was overlooked i corrected it and the other error is not showing up anymore. thank you for pointing that out – Carlo A Feb 17 '22 at 05:13
  • That error seems pretty clear too, `this.allPlumber` is undefined. Try instantiating it `allPlumber: plumberModel[] = [];` – Chris Hamilton Feb 17 '22 at 05:18
  • oopps, sorry I was busy typing, it's all good now, it's connected, however it shows [object, Object] when auto completing, i think I'm still missing a part somewhere where i need to specify the plumbername – Carlo A Feb 17 '22 at 05:27
  • You have ``{{plumber}}`` in your html instead of `{{plumber.plumberName}}` – Chris Hamilton Feb 17 '22 at 05:31
  • Awesome as always @Chris, the autocomplete now works however new error pops on my console whenever I type and click the value. `value.toLowerCase is not a function at UpdateJOComponent._filter` is showing referring to `private _filter(value: string) : plumberModel[] { const filterValue = value.toLowerCase(); return this.allPlumber.filter(plumber => plumber.plumberName.toLowerCase().includes(filterValue))` , I think because I declared ` plumbers: string[] = [];`?? sorry for being a newbie and again thank you for the help – Carlo A Feb 17 '22 at 05:51
  • Take a deep breath and read the error message carefully... `value.toLowerCase()` is not a function, that means `value` is not a string. I have confidence you can backtrack and figure it out. Keep in mind just because you declared the `value` parameter as a string does not guarantee the value you pass in at runtime is a string. – Chris Hamilton Feb 17 '22 at 06:01

0 Answers0