Anguler
code: JavaScript
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
title = 'HelloAnguler';
isAnguler = true;
}
<div *ngIf="isAnguler">Anguler!</div> //*ngIfで表示切替
ng generate component ~~
code:TypeScript
<h2>社員</h2>
<ul class="members">
<li *ngFor="let member of members" (click)="onSelect(member)">
<span class="badge">{{ member.id }}</span> {{ member.name }}
</li>
</ul>
<h2>{{ member.name }}</h2>
<div><span>id: </span>{{ member.id }}</div>
<div><label>名前:
<input type="text" (ngModel)="member.name" placeholder="名前"> </label></div>
*ngFor=""で繰り返し、(click)="onSelect"(member)でクリックしたときに実行するイベントを設定
code: TypeScript
<h2>社員</h2>
<ul class="members">
<li
*ngFor="let member of members"
(click)="onSelect(member)"
class.selected="member === selectedMember" // memberがselectedMemberと一致するならclassにselected属性を付与する <span class="badge">{{ member.id }}</span> {{ member.name }}
</li>
</ul>
<app-member-detail member="selectedMember"></app-member-detail> // memberというプロパティにselectedMemberを受け取り格納する -------------------------------------------------------------------------------------------------------
import { Component, Input, OnInit } from '@angular/core';
import { Member } from '../member';
@Component({
selector: 'app-member-detail',
templateUrl: './member-detail.component.html',
})
export class MemberDetailComponent implements OnInit {
@Input() member: Member; // @Inputデコレーターを用いて、プロパティとして受け取るmemberを定義する
constructor() { }
ngOnInit(): void {
}
}
サービス
データの処理などのビジネスロジックをサービスとしてきり分ける
ng generate service member
code: TypeScript
import { Injectable } from '@angular/core';
import { Member } from './member';
import { MEMBERS } from './mock-members';
@Injectable({
providedIn: 'root'
})
export class MemberService {
constructor() { }
getMembers(): Member[] {
return MEMBERS;
}
}
memberサービスをコンポーネントで使う
code: TypeScript
import { Component, OnInit } from '@angular/core';
import { Member } from '../member';
// import { MEMBERS } from '../mock-members';
import { MemberService } from '../member.service';
@Component({
selector: 'app-members',
templateUrl: './members.component.html',
})
export class MembersComponent implements OnInit {
members: Member[];
selectedMember: Member;
constructor(private memberService: MemberService) { // 依存性の注入。サービスを使う場合コンストラクターの引数
}
ngOnInit(): void { //ライフサイクルメソッド、コンポーネントが初期化されると実行される
this.getMembers();
}
onSelect(member: Member): void {
this.selectedMember = member;
}
getMembers(): void {
this.members = this.memberService.getMembers();
}
}
非同期にデータ取得
RxjsのObservablを使う
code: TypeScript
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { Member } from './member';
import { MEMBERS } from './mock-members';
@Injectable({
providedIn: 'root'
})
export class MemberService {
constructor() { }
getMembers(): Observable<Member[]> { // 帰り値の型をObservablにする
return of(MEMBERS); // of()で渡した値をObservableというオブジェクト型に変換して返す
}
}
------------------------------------------------------------------------------------------------------------
getMembers(): void {
this.memberService.getMembers().subscribe(members => this.members = members);
}
subscribe()内の関数で引数として受け取る、引数は関数
ルーティングコマンド
ng generate module app-routeing --flat --module=app
code: TypeScript
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; // ルーティングに必要なモジュールをインポート
import { MembersComponent } from './members/members.component';
const routes: Routes = [ //
{ path: 'members', component: MembersComponent }
];
@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [
RouterModule
]
})
export class AppRouteingModule { }
code: TypeScript
export class MemberDetailComponent implements OnInit {
@Input() member: Member;
constructor(private route: ActivatedRoute, private memberServise: MemberService, private location: Location) { }
ngOnInit(): void {
}
const id = +this.route.snapshot.paramMap.get('id'); // get()のidはapp-routeingのroutesのidを取得する
// 先頭に+を付けることで数値化できる
}
private route: ActivatedRoute→URLのパラメータ、ハッシュフラグメントを取得する
private location: Location→ブラウザバックやブラウザを進めるのに使う
snapshot→直前のルート情報が含まれている
paramMap→URLのパラメータ情報が格納されている
code: TypeScript
import { HttpClient } from '@angular/common/http' // Http通信ができるモジュールをインポート
private membersUrl = 'api/members'
constructor(private messageService: MessageService, private http: HttpClient) { } // DIして使う
getMember(): Observable<Member[]> {
this.messageService.add('MessageService: 社員一覧データを取得しました');
return this.http.get<Member[]>(this.membersUrl) // get、post、putなどが使える, <Member[]>で帰り値の型を指定する
}
httpエラーハンドリング
code: TypeScript
import { catchError } from 'rxjs/operators';
import { catchError, map, tap } from 'rxjs/operators'; // エラーハンドリング
getMember(): Observable<Member[]> {
this.messageService.add('MessageService: 社員一覧データを取得しました');
return this.http.get<Member[]>(this.membersUrl)
.pipe(tap(members => this.log('~~~~~~~')), catchError(this.handleError<Member[]>('getMembers', [])));
}
private log(message: string){
this.messageService.add(memberServise: ${message});
}
Observableを返す場合.pipe()メソッドでデータを受け取るまでの中間処理を実装できる
pipe(tap(), catchError(this.handleError<Member[]>('getMembers', [])))内は最初に書かれたメソッドから順に実行される
tap()は受け取った値を確認するための関数
code: Typescript
<label>社員名:
<input type="text" #memberName> // テンプレート変数、こう書くとmemberNameという名前でinputタグをを直接参照できる </label>
code:TypeScript
<div id="search-component">
<h4><label for="search-box">社員検索</label></h4>
<input type="text" #searchBox id="search-box" (input)="search(searchBox.value)"> <ul class="search-result">
<li *ngFor="let member of members$ | async">
<a routerLink="/detail/{{ member.id }}">{{ member.name }}</a>
</li>
</ul>
</div>
~~ members$ | async"
members$にはObservableが格納されている、このObservableをテンプレートでサブスクライブできる。
.subscuribe()を実行するのではなくタグの中で自動で実行できる
Observer
Observerはオブジェクトです。
3つの関数をまとめて一つのオブジェクトにしたものです。
3つの関数とは、 「next」「error」「complete」の3つです。
Subscribe
Subscribeは関数です。なので以下では時々「Subscribe関数」と呼びます。
Subscribe関数は、Observerを受け取って、Observerの中にある関数(next,error,complete)を実行します。
どういう順序で、どういう引数を与えて実行するかは、Subscribe関数内に記述します。
code: TypeScript
search(term: string): void {
this.searchTerms.next(term);
}
ngOnInit(): void {
this.searchTerms.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap((term: string) => this.memberService.searchMembsers(term))
)
}
next()を使うことで下のpipeメソッドを通してサブスクライブしている部分にデータを送れる(この場合はof members$ | asyncの部分)
任意のタイミングで値を渡せる。
debounceTime(300)→キーボード入力の後300ms待って次の実行に移る。
distinctUntilChanged()→直前のデータと同じ場合は処理を実行しない。
switchMap((term: string) => this.memberService.searchMembsers(term))→検索キーワードを受け取るたびに、新しいObservableを返す
Observable:データを流す為の川
Operator:データを加工する中間処理
Subscribe:データを受け取るメソッド
code: Typescript
import { interval, Observable } from 'rxjs';
import { map, switchMap, take } from 'rxjs/operators';
// ストリーム(A)に流れてくるデータを元に、別のストリーム(B)を流す。
// 別のストリーム(B)が終わる前に、元のストリーム(A)が流れた場合、
// (B)は途中でキャンセル・破棄され、始めから再び実行される
Observable
.pipe(
switchMap(value => {
return interval(1000).pipe(
take(5),
map((index) => switchMap: ${index} => ${value})
);
});
);
code: TypeScript
import { Observable } from 'rxjs';
import { map, skip } from 'rxjs/operators';
// 指定回数分のストリームを流さず、スキップする
Observable
.pipe(
skip(3),
map(value => skip: ${value})
);
Subjectは任意のタイミングでデータを流せる
Observablでは1回しか流せない
code: TypeScript
private searchTerms = new Subject<string>();
public searchTerms$ = this.searchTerms.asObservable(); // asObservable()でObservablを取得する、コンポーネントから取得できるようにする
public search(term: string): void{
this.searchTerms.next(term); // nextでSubjectを実行
}
----------------コンポーネント---------------------------------------------------
constructor(private searchService: SearchService, private memberService){}
search(term: string): void{
this.searchService.search(term);
}
ngOnInit(): void{
this.members$ = this.searchService.searchTerm$.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap((term: string) => this.memberService.searchMembers(term)),
);
}
ng serve --host=0.0.0.0 --disableHostCheck
--disableHostCheckは許可していない通信接続を解除できる