Angular整理

メモ

ngFor
ngIf
補間 {{ }}
プロパティバインディング [ ]
イベントバインディング ( )

入力として製品を受け取る
import { Input } from '@angular/core'; @Input() product;

*ngFor はAngularの 繰り返し ディレクティブです。

ディレクティブ - Angular の基礎 - Angular 入門

ディレクィブ

Angular では次の3種類のディレクティブ があります。

コンポーネント
構造ディレクティブ (structural directives)
属性ディレクティブ (attribute directives)

コンポーネント

コンポーネントはビュー (View) を制御します。ビューは画面の一部分です。
コンポーネントは @Component 修飾子のついたメタデータをもつ TypeScript クラスです。

メタデータにてビューの HTML テンプレートを定義し、同クラス内のメンバーによってテンプレート内のデータを制御します。

コンポーネント - Angular の基礎 - Angular 入門

構造ディレクティブ (structural directives)

ngIf

ngFor
繰り返し

ngSwitch

ng-template
dom要素を汚さない

angular.keicode.com
angular.jp

Angular のテンプレート システムで使えるビルトインの構造ディレクティブは、 主に次のものが挙げられます。 HTML のレイアウトを担当します。

NgIf - DOM 要素の表示非表示の切替え NgFor - DOM 要素の繰り返し表示 NgSwitch - 条件に応じた振分け

属性ディレクティブ (attribute directives)

既存の DOM 要素の属性を変更することによって、DOM 要素の見た目や振る舞いを変更するものです。
NgClass
NgStyle
NgModel []で囲んで使用 例)

      <button
        class="btn"
        [ngClass]="okButtonClass"
        >OK</button>

angular.keicode.com

プロパティバインディング

www.atmarkit.co.jp
要素オブジェクトのプロパティに値をバインドすること。

angular.keicode.com プロパティ・バインディングは、 コンポーネントのプロパティからテンプレートの DOM 属性 (アトリビュート) に値を渡す方法です。

<p><input [value]="message"></p>
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  message = 'Hello!';

}

イベントバイディング

Angularドキュメント
Angular 日本語ドキュメンテーション

・inputイベント
即時チェック
mosapride.com

<input type="text" (input)="check($event.target.value)">
<div>{{msg}}</div>
  msg : string;
// ------
  check(val:string): void {
    if (event.target.value(/^[a-zA-Z]+$/)) {
      this.msg = 'OK';
    } else {
      this.msg = 'NG';
    }
  }

blurイベント

developer.mozilla.org Dom要素で言えば、 addEventListnerで'blur'を指定すると、カーソルが離れた時を意味する。

qiita.com

(blur)=chage()もカーソルが該当箇所から離れた時に発生する処理である。

コンポーネント

チュートリアルの例
angular.jp

コンポーネントからのイベントのリスニング、子プロパティの読み取り、子メソッドの呼び出し、および親子内での双方向通信のためのサービス箇所

@Inputにより、親からの値を取得できる。

(抜粋)
"Notify Me"ボタンを機能させるには、次の2つの設定が必要です。
ユーザーが"Notify Me"をクリックしたときにイベントを発行する商品アラートコンポーネント
そのイベントに反応する商品リストコンポーネント

src/app/product-list/product-list.component.html

<button (click)="share()">
  Share
</button>

<app-product-alerts
  [product]="product">
</app-product-alerts>

src/app/product-alerts/product-alerts.component.ts

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


@Component({
  selector: 'app-product-alerts',
  templateUrl: './product-alerts.component.html',
  styleUrls: ['./product-alerts.component.css']
})
export class ProductAlertsComponent implements OnInit {
//このproductは、product-list.component.htmlの [product]="product"
//の ""のproductを表している!!
  @Input() product;
  @Output() notify = new EventEmitter();

  constructor() { }

  ngOnInit() {
  }

}

src/app/product-alerts/product-alerts.component.html

<button (click)="share()">
  Share
</button>

<app-product-alerts
  [product]="product" 
  (notify)="onNotify()">
</app-product-alerts>

src/app/product-list/product-list.component.ts

export class ProductListComponent {
  products = products;

  share() {
    window.alert('The product has been shared!');
  }

  onNotify() {
    window.alert('You will be notified when the product goes on sale');
  }
}

サービスを利用する

@Injectable

該当モジュールのprovidersに追加

・データをserviceからデータを取り出す時、

  constructor(
    private cartService: CartService
  ) { }
  ngOnInit() {
    this.items = this.cartService.getItems();
  }

というように書く。

サービスを利用しない場合は、

NgModel

qiita.com
双方向バインディングという。
Angular2では

 <input [(ngModel)]="firstName">

と書けば、これを利用してるページでの currentHero.firstName との双方向バインディングが出来ます。
→言い換えると、
qiita.com
コンポーネントの値とテンプレート上の値とを双方向に同期させるためのバインド構文を双方向バインディングと言います。
ngModelディレクティブという。

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

@Component({
  selector: 'app-root',
  template: `
    <form>
      <label for="name">名前:</label>
      <!--[1]テキストボックスtxtNameに対して、nameプロパティをひも付け-->
      <input id="txtName" name="txtName" type="text"
        [(ngModel)]="name" />
      <!--[2]nameプロパティをもとに挨拶メッセージを生成-->
      <div>Hello, {{name}}!!</div>
    </form>
  `,
})
export class AppComponent  {
  // [3]デフォルト値を設定
  name = 'Tom';
}

双方向バインディングでは、ngModelディレクティブを[(...)]でくくります。[...]はProperty Binding(コンポーネント→テンプレート)を、(...)はEvent Binding(テンプレート→コンポーネント)を表しますので、両者を組み合わせたのが[(...)](双方向バインディング)というわけです。

www.atmarkit.co.jp
双方向バインディングの仕組みを理解するために、[1]のコードを双方向バインディングを利用せずに表してみましょう。

<input id="txtName" name="txtName" type="text"
  [ngModel]="name"
  (input)="name=$event.target.value" />

・propertyバイディング で記載
まず、[ngModel]="name"でnameプロパティの値をngModelディレクティブにバインドします。Property Binding構文です。

・イベントバイディング ()で記載
 「(input)="name=$event.target.value"」はEvent Bindingの構文で、inputイベント(=入力値が変更された)のタイミングで、ターゲット要素($event.target*2)の値(value)をnameプロパティに代入します。

(ngModel)を自作する例あり

[https://qiita.com/kohashi/items/bcbcc9cbeaee9498e4fe:title]
@Inputと@Outputが同じコンポーネントで使用されている。

@Input、@Output

次に出てくる@Outputで吟味したはずだが、まだ見ても理解できない
[https://qiita.com/masaks/items/677195b78379e0877e24:embed:cite]

Lifecycle Hooksとは

[https://blog.yuhiisk.com/archive/2016/05/02/angular2-lifecycle-hooks.html:embed:cite]

@Output

[https://mae.chab.in/archives/59992:embed:cite]
※重要箇所抜粋 ほとんど全部
Angularでは、親コンポーネントから子コンポーネントに値を渡す場合は、まず親コンポーネント側でプロパティバインディング()に値を渡し、子コンポーネント側で@Inputを通して受け取ります。
@Outputはこの逆を行うものと考えてもらえれば良いでしょう。つまり、子コンポーネントから親コンポーネントに値を渡したい場合や、また子コンポーネントで発生したアクションを親コンポーネントに伝えたい場合に使います。

「カスタムイベント」(カスタムイベントという!!!)であるsendValueが子コンポーネントのアクション(emit)により発火した際にイベントハンドラのコールバック関数として定義したhandleSendValueメソッドが呼ばれるようになっています。

以下は子コンポーネントのChildComponentです。ここもあえてReact的に言うと、親コンポーネントから渡されたsendValueを@Output()を通して受け取ります。Angular的に言うと、sendValue(親コンポーネントから渡されたもの)をイベントを発生させるエミッターとして定義します。その際に@Output()でデコレートすることで、親コンポーネントに通知ができるようになります。

1.@Outputを使用するには、EventEmitterが必要
EventEmitterってなんぞやという感じだが、要は子コンポーネントで、親コンポーネントのhogeEventイベントを以下のようにする。
よくわからん。
@Output() hogeEvent: EventEmitter = new EventEmitter();

emitとは

とりあえず、子コンポーネントで、@Outputデコレータを定義。
ここで@Outputで定義するのは親コンポーネントのカスタムタグであるはず。
これで親コンポーネントでイベントを発生させると、emitで発火させるというイメージで良いであろう。
emitされた値を親コンポーネントが受け取る。emitはここで発生するという認識で今のところ良い。

・Observableとは
サーバと通信するにあたって、データを観測するクラス「Observable」
[https://qiita.com/Yamamoto0525/items/efc0e5617c7427fea86a:embed:cite]

リアクティブフォーム

ちょくちょく出てくるんで今のうちにたたいておく。

[https://minase-program.hatenablog.com/entry/2018/10/30/011324:embed:cite]

リアクティブフォーム は、時間とともに入力値が変わるフォームを扱うためのモデル駆動なアプローチを提供します。
・app.module.tsにimport

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    // other imports ...
    ReactiveFormsModule
  ],
})
export class AppModule { }

@NgModuleに追加

生成されてるapp.component.htmlとapp.component.tsを下記の通りに変える。

import { Component } from '@angular/core';
import { FormControl,Validators } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public control = new FormControl('', [
    Validators.required
  ]);
}
入力欄:<input type="text" [formControl]="control" required>
<div *ngIf="control.invalid && (control.dirty || control.touched)">
  <span *ngIf="control.hasError('required')">必須です。</span>
</div>

要は、プロパティバイディングで、即時反映しているということである。 プロパティバイディングは本日何度も言っているが、コンポーネントの値を、テンプレートで反映し、{{}}を使うと、 即時に反映されるということである。
プロパティであるが、 www.atmarkit.co.jp

import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  template: `<a [href]="url">サポートサイトへ</a>`
})
export class AppComponent {
  url = 'http://www.wings.msn.to/';
}

hrefがプロパティである。つまりhtmlのタグのことである。
じゃあ、[formControl]が何かということであるが、恐らくhrefとかのような標準ではないが、 importしたReactiveFormsModuleにより、使える機能であろう。
どんな機能かと言えばバリデーションである。
本家にも載っている。
angular.jp

よく出てくるngModelとはなにか?

属性ディレクティブのこと。既出。

@NgModuleについて

モジュールの呼び方参照

[Angular] JavaScriptのモジュール - @NgModuleとは何か (1) - Qiita

[Angular] JavaScriptモジュール vs. NgModule - @NgModuleとは何か (2) - Qiita

NgModuleは@NgModuleによって修飾されたクラスです
@NgModuleとメタデータがあることでNgModuleになります。 →説明になっていない!

[Angular] ブートストラップ - @NgModuleとは何か (3) - Qiita

[Angular] よく使われるモジュール達 - @NgModuleとは何か (4) - Qiita

コンポーンネント、テンプレート含めてcliで作成することをなんというのか

cliコンポーネントを作るでいいらしい。テンプレートやcssファイルも含むらしい。

モジュールの呼び方

qiita.com
app.module.tsをルートモジュールとし、新しく作成されたcore.module.tsをコアモジュール、shared.module.tsを共有モジュールとして扱っていきます。

↓以下重要!! ユーザーがアプリを起動後、最初に実行されるのがルートモジュールです。 ルートモジュールであるapp.module.tsを見てみると、@NgModuleというデコレータのbootstrapというプロパティにAppComponentが指定されています。 これは最初に読み込むコンポーネントをAppComponentに指定したという意味になります。