web-dev-qa-db-ja.com

Angular5 httpClient get:未定義のプロパティ「toLowerCase」を読み取れません

APIからユーザーのリストを取得しようとしていますが、次のエラーが表示されます。

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)

HttpClientを使用してユーザーを取得するhomeService.getUsers()を呼び出すログインコンポーネントがありますが、http要求はサーバーに到達しません。

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);
  }
}

Home.service:

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);
  }

}

および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 { }

ログにエラーメッセージが表示されているので、HttpClientからのエラーのように見えます。しかし、Httpリクエストをサーバーに送信する前に失敗する理由を理解することはできません。

7
Canlla

同じ問題が発生しました。問題は、URLを宣言したことですが、httpgetを実行すると、URLに値が割り当てられていないことに気付きました。

考えられるケース:例:private yourUrl:string;

そして、http呼び出しで:this.http.get(this.yourUrl、{headers:this.headers})を返します

11
Sri

変数を誤って宣言したため、未定義になっているようです:試してみてください

きちんとしたコーディングのために

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

user: User;

また、この行を修正します

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

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

これは問題がある可能性が高い場所です

6
Talabi Opemipo

あなたのURL宣言が正しくないと思うのは、次の方法を試してください:

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

0
faiaz000

同じ問題がありました。 @Canllaが言ったように、url変数の可視性をpublicからprivateに変更する必要がありました。

奇妙ですが、何かがその価値を変えていました!とにかく、それは私たちがタンプレートにアクセスする必要がないので、プライベートでなければなりません。

私の場合、さらに、ロードが完了する前にデータバインディングを回避するためにNgIf/NgElseを追加する必要がありました。

<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>

ここに:<mat-list *ngIf="transactions | async; let transactions;else loading">

asyncパイプに* ngIfがあり、mat-listtransactionsがロードされた場合。次 let userステートメントがtrueの場合、AngularはObservableから値を割り当てるローカルテンプレート変数を作成します。

さもないと else loading tells Angularロード中のテンプレートを表示するための条件が満たされない場合。

@coryrylanのこの優れた投稿をご覧ください。 https://coryrylan.com/blog/angular-async-data-binding-with-ng-if-and-ng-else

0
Maicon Heck