ふらぱいく

備忘録。いい加減つける

Angular 入門してみる4

Angular 入門

今回はコンポーネントの分割,外部データの参照。

template部分を機能ごとに分割

member一覧とclickした際の詳細画面をそれぞれ別のComponentとして扱う。
詳細画面ファイルmember-detail.component.tsを作成し,selectedMemberクラスのdivタグをtemplateに移動。

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

@Component({
  selector: 'member-detail',
  template: `
    <div *ngIf="selectedMember">
      <div>
        id: {{selectedMember.id}}
      </div>
      <div>
        name: {{selectedMember.name}}
      </div>
      <div>
        <input type="text" [(ngModel)]="selectedMember.name">
      </div>
    </div>
  `
})

export class MemberDetailComponent {
}

app.module.ts に追加。

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';

import { AppComponent }  from './app.component';
// tslint:disable-next-line:quotemark
import {MemberDetailComponent} from './member-detail.component';

@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [ AppComponent, MemberDetailComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

基本的に1ファイル1クラスなので,app.componentのMemberクラスを新ファイル「member.ts」に移動。importを忘れずに。
member-detail.component.tsで,selectedMemberを取得することができなくなったため先程移動したMemberプロパティを参照する。この際,selectedMemberはmemberにリファクタ。

import {Component} from '@angular/core';
import {Member} from './member';

@Component({
  selector: 'member-detail',
  template: `
    <div *ngIf="member">
      <div>
        id: {{member.id}}
      </div>
      <div>
        name: {{member.name}}
      </div>
      <div>
        <input type="text" [(ngModel)]="member.name">
      </div>
    </div>
  `
})

export class MemberDetailComponent {
  member: Member;
}

次に,member-detail.componentのtemplateをapp.componentに追加する。
selector がそのままタグの名前となるので,先程移動した箇所に追記。

<h1>{{title}}</h1>
    
    <ul class="members">
    <li *ngFor="let member of member" 
        (click)="onSelect(member)" 
        [class.selected]="member === selectedMember">
      <span class="badge">{{member.id}}</span>{{member.name}}
    </li>
    </ul>
    <member-detail></member-detail>  <-- 追加 -->
外部データの参照

app.componentでclickイベントによって発火したonSelect()によってselectedMemberが生成されるが,Componentを分割したので詳細templateにデータが反映されない。
このままではmemberをclickしても詳細が出てこないので,外部データを参照する必要がある。
f:id:noinoi_monstS4l:20190601060427p:plain

そこで,Inputデコレータを用いる。
Inputデコレータとは親コンポーネントから子コンポーネントへ,データを受け渡す。
反対に,子コンポーネントから親コンポーネントへのデータの受け渡しにOutput()があるが,実装方法が異なるので割愛。詳しくはココ
f:id:noinoi_monstS4l:20190601055612p:plain


コンポーネントにInputをimportし,受け渡したいプロパティに「@Input」デコレータをセットする。

import {Component, Input} from '@angular/core'; // Angular_coreからimport
import {Member} from './member';

@Component({
  selector: 'member-detail',
  template: `
    <div *ngIf="member">
      <div>
        id: {{member.id}}
      </div>
      <div>
        name: {{member.name}}
      </div>
      <div>
        <input type="text" [(ngModel)]="member.name">
      </div>
    </div>
  `
})

export class MemberDetailComponent {
  @Input() member: Member; // Inputデコレータを追記
}

templateの子Component名のタグの中で,デコレートしたプロパティに受け渡したいデータを代入。

<h1>{{title}}</h1>
    
    <ul class="members">
    <li *ngFor="let member of member" 
        (click)="onSelect(member)" 
        [class.selected]="member === selectedMember">
      <span class="badge">{{member.id}}</span>{{member.name}}
    </li>
    </ul>
    <member-detail [member]="selectedMember"></member-detail> <-- []で囲む -->

f:id:noinoi_monstS4l:20190601060242p:plain

以上。次回はLifeCycleHook。