web-dev-qa-db-fra.com

Angular5 httpClient get: Impossible de lire la propriété 'toLowerCase' de non définie

J'essaie d'obtenir une liste d'utilisateurs à partir d'une API, mais l'erreur suivante apparaît:

TypeError: Cannot read property 'toLowerCase' of undefined
at HttpXsrfInterceptor.intercept (http.js:2482)
at HttpInterceptorHandler.handle (http.js:1796)
at HttpInterceptingHandler.handle (http.js:2547)
at MergeMapSubscriber.eval [as project] (http.js:1466)
at MergeMapSubscriber._tryNext (mergeMap.js:128)
at MergeMapSubscriber._next (mergeMap.js:118)
at MergeMapSubscriber.Subscriber.next (Subscriber.js:92)
at ScalarObservable._subscribe (ScalarObservable.js:51)
at ScalarObservable.Observable._trySubscribe (Observable.js:172)
at ScalarObservable.Observable.subscribe (Observable.js:160)

J'ai un composant de connexion qui appelle homeService.getUsers () qui utilise HttpClient pour récupérer les utilisateurs, mais la demande http n'atteint jamais le serveur.

login.component.ts:

import { Component, OnInit } from '@angular/core';

import { HomeService } from '../service/home.service';
import { User } from '../domain/user';

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

  user: User = {
      id: undefined,
      userName: undefined,
      password: undefined
  }; 
  users: User[];

  constructor(
    private homeService: HomeService
  ) { }

  ngOnInit() {
    this.getUsers();
  }

  getUsers(): void {
    this.homeService.getUsers()
    .subscribe(users => this.users = users);
  }
}

Service à domicile:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';

import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { catchError, map, tap } from 'rxjs/operators';

import { User } from '../domain/user';
import { MessageService } from '../service/message.service';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

@Injectable()
export class HomeService {

  private usersUrl: 'http://localhost:8080/users';

  constructor(
    private http: HttpClient,
    private messageService: MessageService
  ) { }

  getUsers (): Observable<User[]> {
    return this.http.get<User[]>(this.usersUrl)
      .pipe(
        tap(users => this.log(`fetched users`)),
        catchError(this.handleError('getUsers', []))
      );
  }

  /**
  * Handle Http operation that failed.
  * Let the app continue.
  * @param operation - name of the operation that failed
  * @param result - optional value to return as the observable result
  */
  private handleError<T> (operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {

      // TODO: send the error to remote logging infrastructure
      console.error(error); // log to console instead

      // TODO: better job of transforming error for user consumption
      this.log(`${operation} failed: ${error.message}`);

      // Let the app keep running by returning an empty result.
      return of(result as T);
    };
  }

  private log(message: string) {
    this.messageService.add(message);
  }

}

et l'app.module:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientXsrfModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { HomeService } from './service/home.service';
import { MessagesComponent } from './messages/messages.component';
import { MessageService } from './service/message.service';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    LoginComponent,
    RegisterComponent,
    MessagesComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    HttpClientXsrfModule.withOptions({
      cookieName: 'My-Xsrf-Cookie',
      headerName: 'My-Xsrf-Header',
    })
  ],
  providers: [HomeService, MessageService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Je peux voir le message d'erreur affiché dans la journalisation, cela ressemble donc à une erreur du HttpClient. Mais je ne peux pas comprendre pourquoi il échoue avant d'envoyer la demande Http au serveur.

5
Canlla

J'ai le même problème. Le problème était que j'avais déclaré l'URL, mais en faisant le httpget, j'ai réalisé que l'URL n'avait reçu aucune valeur:

Cas probable: Exemple: Private yourUrl: string; 

et dans votre appel http: return this.http.get (this.votreUrl, {en-têtes: this.headers})

6
Sri

il semble que vous ayez déclaré une variable à tort, la rendant ainsi non définie: 

Pour un codage soigné 

interface User = {
      id: number;
      userName: string;
      password: string;
  }

user: User;

Corrigez également cette ligne de

private usersUrl: 'http://localhost:8080/users';

À

private usersUrl =  'http://localhost:8080/users';

C’est probablement là où se trouve le problème

3
Talabi Opemipo

J'ai eu le même problème…. Comme @Canlla l'a dit, il était nécessaire de changer la visibilité de la variable url de public à privé.

Étrange, mais quelque chose changeait de valeur! En tout cas, ça doit être privé, puisque nous n’avons pas besoin d’avoir accès au tamplate.

Dans mon cas, en outre, je devais ajouter NgIf/NgElse pour éviter la liaison de données avant la fin du chargement:

<mat-list *ngIf="transactions | async; let transactions;else loading">
      <div *ngFor="let transaction of transactions">
        <h3 mat-subheader>{{ transaction.dueDate }}</h3>        
        <mat-list-item>
          <img matListAvatar src="https://source.unsplash.com/random/100x100" alt="...">
          <span matLine class="mat-body-2"> {{transaction.description}} </span>
          <p matLine class="col col-6 left-align">
            <span class="mat-body-1"> {{transaction.categoryName}} </span>
            <br>
            <span class="mat-caption"> {{transaction.accountName}} </span>
          </p>
          <p class="col col-6 right-align">
            <span class="mat-subheading">{{ transaction.amount | currency:'BRL':'symbol' }}</span>
          </p>
        </mat-list-item>       
      </div>
    </mat-list>

<ng-template #loading>Loading...</ng-template>

Donc, ici: <mat-list *ngIf="transactions | async; let transactions;else loading">

J'ai * ngIf avec async pipe pour montrer mat-list si transactions a chargé . Prochaine instruction let user si true, créant une variable de modèle local qu'Angular affecte à la valeur Observable.

Sinon, else loading indique à Angular si la condition n'est pas remplie pour afficher le modèle de chargement.

Découvrez-le dans cet excellent post de @coryrylan: https://coryrylan.com/blog/angular-async-data-binding-with-ng-if-and-ng-else

0
Maicon Heck