anakin59490
anakin59490

Reputation: 672

Angular 5 Angular Material 2 - autocomplete with minLength

I added autocomplete field on my form in order to select a patient. The patient data come from database. The problem is there are 40.000 patients

So i would like to load data after user has entered 3 characters minimum. But i don't know how to check that and how to pass the input to the function (filter argument). This is what i have done. for the moment the data are loaded when i click on the input field :

HTML :

<mat-form-field class="index-full-width">
                    <input
                      matInput
                      type="text"
                      [(ngModel)]="patientChoice"
                      placeholder="Patient"
                      aria-label="Patient"
                      [matAutocomplete]="autoPatient"
                      [formControl]="myControl"
                      (click)="getPatients()">
                    <mat-autocomplete (optionSelected)="selectPat()" #autoPatient="matAutocomplete" [displayWith]="displayFnPat">

                      <mat-option *ngFor="let patient of filteredPatients | async" [value]="patient">
                        <span>{{ patient.lastName }}</span>
                        <small>{{patient.firstName}}</small> |
                        <span>né(e) le {{ patient.dateNaissance }}</span> |
                        <small>IPP: {{patient.ipp}}</small>
                      </mat-option>
                    </mat-autocomplete>
                  </mat-form-field>

TS :

 getPatients() {
let searchTerm = '*';
let success: any = {};
this.klinckServices.getPatients(searchTerm)
  .then((webScriptdata) => {
      success = webScriptdata;
      this.listPatients = success.data.items ;
      console.log(this.listPatients);
    },
    msg => {
      alert(msg);
    });

}

 ngOnInit() {
this.filteredPatients = this.myControl.valueChanges.pipe(
  startWith<string | Patient>(''),
  map(patient => typeof patient === 'string' ? patient : patient.name),
  map(name => name ? this.filterPatient(name) : this.listPatients.slice())
);

 }
  displayFnPat(patient: Patient): string | undefined {
return patient ? patient.name : undefined;
 }


 filterPatient(name: string) {
   return this.listPatients.filter(patient =>
    patient.name.toLowerCase().includes(name.toLowerCase()));
 }

Upvotes: 1

Views: 7866

Answers (2)

anakin59490
anakin59490

Reputation: 672

OK, solved by adding in HTML (keyup)="getPatients($event)" :

<input
    matInput
    type="text"
    [(ngModel)]="patientChoice"
    placeholder="Patient"
    aria-label="Patient"
    [matAutocomplete]="autoPatient"
    [formControl]="myControl"
    (keyup)="getPatients($event)"
 >

And in TS file :

    getPatients(event: any) {
    let searchTerm = '';
    searchTerm += event.target.value;
    console.log(searchTerm);
    if (searchTerm.length === 2) {
      let success: any = {};
      this.klinckServices.getPatients(searchTerm)
        .then((webScriptdata) => {
            success = webScriptdata;
            this.listPatients = success.data.items;
            console.log(this.listPatients);
          },
          msg => {
            alert(msg);
          });
    }
  }

Upvotes: 1

waveiro
waveiro

Reputation: 183

There's another way to do it and it is recommended here.

It's basically checking the length on your filter method.

  filterPatient(name: string) {
    if (name.length < 2) {
      return [];
    }

    return this.listPatients.filter(patient =>
      patient.name.toLowerCase().includes(name.toLowerCase()));
  }

Upvotes: 3

Related Questions