大田区から発信するゆるゆる日記

主にITエンジニアに関する備忘録日記。たまに趣味も。何か不備があればコメント頂けると幸いです。Twitterアカウント https://twitter.com/ryuzan03

【Angular/MongoDB/エラー】オブジェクトデータの表示

※下記の内容に不備がありましたら、コメント頂けると幸いです。また、下記の内容をご使用頂ける場合は自己責任でお願いします。

【目次】

 

背景

LaravelでMongoDBからデータを取得して、Angularで表示させようとしたら、[object Object]が表示されました。

 

これを解決するのにとても苦労したので、その原因とデータの表示方法を備忘録として書きます。

 

本当はネストが深い場合でのオブジェクトデータの表示に苦労したのですが、私の場合はそもそもオブジェクトデータについて間違った認識をしていていたので、今回はネストがない場合でのオブジェクトデータの表示から詳しく書いていきます。

 

ネストが深い場合の記事は明日以降に書きます。

【2/6 追記】

ネストが深いオブジェクトデータの表示について記事を書きました。

【Angular/MongoDB】ネストが深いオブジェクトの表示 - 大田区から発信するゆるゆる日記

 

 

オブジェクトの表示

問題の内容

以下の環境で開発を行っています。

  • Angular
  • Laravel
  • MongoDB

 

MongoDBにあるオブジェクトをLaravelで取得し、Angularでリッチに表示させようとしていました。

 

Angularのcomponent.htmlで以下のコードを書いたら、サイトでは[object Object]が表示されていました。

※今回はcomponent.ts内にオブジェクトのデータを入れています。本来であれば、service.tsでLaravelからデータを取得しているので、component.ts内に下記のapiDataデータは不要です。

 

component.ts

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public apiData=
            {
              "id":154,
              "page_id":79,
              "user_id":1548,
              "text":"this is the first message",
              "created_at":"2019-04-10 13:54:10",
"updated_at":"2019-04-10 13:54:10"}
}

 

component.html

<p *ngFor="let j of apiData">
  {{ p }}
</p>

 

localhost 

[object Object]

 

 

原因

  • オブジェクトはそのままでhtmlに表示できない
  • オブジェクトと配列は違う
  • オブジェクトと連想配列は場合によっては同意義

 

総じると、オブジェクトと配列を同じと捉えていたのが、解決までに時間がかかってしまった原因でした。

 

オブジェクトはそのままではhtmlに表示をさせることができません。

 

また、ややこしいことにオブジェクトはjavascriptオブジェクトや連想配列とも呼ばれているのですが、JavaScriptではそれらも含めてオブジェクトと呼んでいいみたいです。文献によって言い方が違ったのでややこしかった・・・

JavaScript: 連想配列とオブジェクトの違い

JavaScript: 配列(array)とオブジェクト(object)の違い

 

 

解決方法

オブジェクトデータを配列データやjson文字列に変換すれば幸せになれそうです。

オブジェクトでの作業 - JavaScript | MDN

 

Angularを使っているなら、4のKeyValuePipeを使用するのが良さそうです。

 

 

※オブジェクトデータは上記に記載した【問題の内容】と同じとします。

1.Keyを指定(objectName.propertyName)

オブジェクトでの作業 - JavaScript | MDN

通常のJavaScript変数と同じように、オブジェクトのプロパティ値(Value)はドット表記、もしくはブラケット (角括弧) 記述法でプロパティ名(Key/propertyName)を指定してアクセスします。

 

{{ apiData['id'] }}

or

{{ apiData.id }}

結果

154

or

154

 

ネストが深いと、これは上手くいかないかもしれません。

あと、プロパティ名(Key)を取得することができません。

 

 

2.パイプjson

オブジェクト(javascriptオブジェクト)になっているデータをJSON文字列に変換してくれます。

プロパティ名(Key)やプロパティ値(Value)、括弧なども全て文字列に変換します。

 

{{ apiData | json}}

結果

{ "id": 154, "page_id": 79, "user_id": 1548, "text": "this is the first message", "created_at": "2019-04-10 13:54:10", "updated_at": "2019-04-10 13:54:10" }

 

このままでは使えないですね。

 

 

3.Object.keysメソッド(Angular6以下)

Object.keys() - JavaScript | MDN

このメソッドはオブジェクトデータのプロパティ名(Key)を配列にして返してくれます。

つまり、プロパティ名だけの配列を生成してくれます。

 

Object.keysメソッドを使うには、Object.keysメソッドを一度変数に入れる必要があります。

 

Object.keysメソッドの引数には、メソッドを入れることもできるので、とても便利なメソッドだと思います。

 

component.ts

export class AppComponent  {
  public objectKeys = Object.keys;
}

component.html

<div *ngFor="let key of objectKeys(apiData) ">
  {{ key }}:{{ apiData[key] }}
</div>

 

結果

id:154
page_id:79
user_id:1548
text:this is the first message to be sent by joe
created_at:2019-04-10 13:54:10
updated_at:2019-04-10 13:54:10

 

合わせて、Object.valuesメソッドも覚えているといいかもです。

Object.values() - JavaScript | MDN

 

使用頻度が多そうなら、パイプ化してしまうのもいいかと思います。

(弊社ではそうしています)

 

 

4.KeyValuePipe(Angular6.1以降)

Angular

Angular6.1以降から登場したパイプです。

CommonModuleのインポートが必要です。

 

プロパティ名を「key」と「value」とする配列を作り、それをオブジェクトにして返します。プロパティ値には引数のプロパティ名(Key)とプロパティ値(Value)が入ります。

{ "key": "created_at", "value": "2019-04-10 13:54:10" }
{ "key": "id", "value": 154 }
{ "key": "page_id", "value": 79 }
{ "key": "text", "value": "this is the first message to be sent by joe" }
{ "key": "updated_at", "value": "2019-04-10 13:54:10" }
{ "key": "user_id", "value": 1548 }

 

module.ts

・・・
import { CommonModule } from '@angular/common';

@NgModule({
  imports:      [  CommonModule ],
})
export class AppModule { }

component.html

<div *ngFor="let j of apiData | keyvalue">
  {{ j.key }}:{{ j.value }}
</div>

結果

created_at:2019-04-10 13:54:10
id:154
page_id:79
text:this is the first message to be sent by joe
updated_at:2019-04-10 13:54:10
user_id:1548

 

順番が変わる…なんでだろ?

 

 

5.for...inループ

for...in - JavaScript | MDN

すみません、あまり使わなさそうだったので省略します!

 

 

6.Object.getOwnPropertyNamesメソッド

Object.getOwnPropertyNames() - JavaScript | MDN

すみません、あまり使わなさそうだったので省略します!

 

 

7.JSON.stringify

JSON.stringify() - JavaScript | MDN

AngularでJavaScriptオブジェクトをJSON形式に変換するには?(json):Angular TIPS - @IT

パイプjsonに相当します。

すみません、あまり使わなさそうだったので省略します!

なお、オブジェクト(プロパティ)の値がundefined、またはfunction型(=メソッド)の場合は、変換の対象外です。

 

 

今後に向けて

ネストが深いともう一手間必要なんですが、この記事の内容が分かっていればさほど手間取ることはないと思います。

 

ネストが深い場合についてはまた今度書きます。

 

※コードをちょっと試す時はこれ便利。

The online code editor for web apps. Powered by Visual Studio Code. - StackBlitz

 

 

参考

素晴らしい記事に感謝いたします。

オブジェクトでの作業 - JavaScript | MDN

https://tutorialmore.com/questions-991072.htm

【Angular】KeyValuePipe の使い方 - 開発覚書はてな版

angular - * ngForを使ってオブジェクトキーを繰り返す方法 - 答えた