LoginSignup
39
33

More than 3 years have passed since last update.

Angularアプリケーションをブラウザのコンソールからデバッグする

Last updated at Posted at 2020-02-24

前提

本記事の内容は主にAngular v9以上を対象としています。
v9よりIvy(Angularの次世代レンダリングエンジン)がデフォルトで有効になり、Ivyの導入に伴いデバッグAPIの仕様が変更されています。
そのため、v8以前では本記事で紹介するデバッグAPIは利用できません。

ブラウザコンソールからAngularの状態を見る

Angularの開発モード(ng serveした状態)では、@angular/core/globalパッケージを使用してコンソールからアプリケーションの状態を見ることができます。
@angular/core/globalパッケージのメンバは、ngという名前空間に属する関数としてグローバル領域(windowオブジェクト内)に公開されます。
コンソールよりng.XXXXと関数を実行することで、コンポーネントのインスタンスなどを取得できます。

window.ng.PNG

以下は使用可能な関数の一覧です。公式APIガイドより抜粋(意訳)したものです。

関数 内容
ng.applyChanges 引数として渡したコンポーネントが属するアプリケーションの変更検知を実行します。(コンポーネントがOnPushの場合、チェック対象としてマークしたうえで実行します。)
ng.getComponent 引数として渡したDOM要素に関連付けられているコンポーネントインスタンスを取得します。
ng.getContext 引数として渡したDOM要素が埋め込みビュー内(*ngIfや*ngFor)にある場合、その要素が属するコンテキストを取得します。それ以外の場合、引数のDOM要素が属するコンポーネントのインスタンスを取得します。(getOwningComponentを実行したときと同じ)
ng.getDirectives 引数として渡したDOM要素に関連付けられているディレクティブインスタンスを取得します。コンポーネントインスタンスは含まれません。
ng.getHostElement 引数として渡したコンポーネントインスタンスまたはディレクティブインスタンスのホスト要素を取得します。
ng.getInjector 引数として渡したDOM要素、コンポーネントインスタンス、ディレクティブインスタンスに関連付けられたインジェクタを取得します。
ng.getListeners 引数として渡したDOM要素に関連付けられたイベントリスナを取得します。ホストリスナを含みますが、Angularコンテキスト外で定義されたイベントリスナ(たとえばaddEventListenerを介したもの)は含まれません。
ng.getOwningComponent 引数として渡したDOM要素をビューに含むコンポーネントインスタンスを取得します。
ng.getRootComponents 引数として渡したDOM要素、コンポーネントインスタンス、ディレクティブインスタンスに関連付けられたルートコンポーネントを取得します。

ユースケース

@angular/core/globalパッケージ(ng.XXXX)を使って実際にどのようなことができるのか、ユースケースを見ていきましょう。

1. バインドする値を変更してビューに反映させる

プロパティバインディングやInterporationなどでコンポーネントインスタンスの変数をビューにバインドしている場合、コンソールを使ってインスタンスの変数を操作し、ビューを変化させることができます。

bind.PNG

たとえば、上記の例ではAppComponenttitle文字列がInterporationでビューに表示されています。
これを以下のようにコンソールから操作します。

  1. DevToolsのインスペクタまたはElementsタブで要素を指定する inspector.PNG
  2. Consoleタブで以下のコマンドを入力
// 要素の属するコンポーネントインスタンスを取得
// ※DevToolsでは選択した要素は「$0」変数に格納されている
const cmp = ng.getOwningComponent($0);

// インスタンスの変数を変更
cmp.title = 'Change value from console';

// ビューの変更検知を実行
ng.applyChanges(cmp);

change-value.PNG

本来ならアプリケーションに実装された正規の手続きを踏んでtitleを変更するべきですが、単純にビューの見た目のチェックをする程度であれば十分有用でしょう。

2. ngForでループされている内容を確認する

ngForは配列などを渡すと内容を展開してビューを形成してくれる便利なディレクティブですが、実際にどのようなデータがngForに渡っているか、見えているビューからすべてを把握することが難しい場合があります。

ngFor.PNG

このような場合、以下のようにしてngForで処理された内容を伺うことができます。

  1. DevToolsのインスペクタまたはElementsタブでngForによって生成された要素を指定する
  2. Consoleタブで以下のコマンドを入力
// 要素の属するコンテキストを取得
// ※DevToolsでは選択した要素は「$0」変数に格納されている
ng.getContext($0);

getContext.PNG

上記の例では一つ目のdiv(配列の最初の要素=aaa)を選択しています。
getContextの戻り値からはNgForOfContext型のオブジェクトが返され、ngForに渡ったデータのほか、indexcountfirstoddといった情報を確認することができます。

3. 任意のイベントを発火させる

Angularでは、子コンポーネントから親コンポーネントへデータを渡す場合、子コンポーネントのEventEmitterを発火させ、コールバックという形で受け渡します。

app.component.html
<app-child (someEvent)="onReceiveValue($event)"></app-child>
app.component.ts
onReceiveValue(e: string): void {
  // ここで何らかの処理
  console.log('event callback');
  console.log(e);
}

以下のようにすると、子コンポーネントの実装によらずにイベント発生を再現し、親コンポーネントのコールバックを実行することができます。

  1. DevToolsのインスペクタまたはElementsタブで子コンポーネント内の要素を指定する
  2. Consoleタブで以下のコマンドを入力
// 要素の属するホスト要素(app-child要素)を取得
// ※DevToolsでは選択した要素は「$0」変数に格納されている
const cmp= ng.getOwningComponent($0);
const host = ng.getHostElement(cmp);

// ホスト要素(app-child要素)のイベントリスナを取得
// ※リスナは配列で返却される
const lsnr = ng.getListeners(host);

// イベントリスナのコールバックを実行
lsnr[0].callback('some value from child component');

event-emitter.PNG

もちろん、親子間のEventEmitter発火のみでなく、通常のクリックイベントなどでも同様にしてコールバックを実行させることができます。

参考

Angular APIガイド: @angular/core/global
Debugging Angular Ivy Applications from the Devtools Console
Console Debugging with window.ng

39
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
33