!!!Angular
[TypeScript][Google Cloud Platform][Bootstrap][Flask]
{{amazon 4774191302}}
!!!Angular CLI
!!インストール
>npm install -g @angular/cli
!!アプリケーションの生成
> ng new myapp
!!アプリケーションの実行
> ng serve
!!Angular CLI の主なコマンド
*https://github.com/angular/angular-cli/wiki
,概要,コマンド
,appアプリを生成,[ng new app|https://github.com/angular/angular-cli/wiki/new]
,ひな形の生成,[ng generate ...|https://github.com/angular/angular-cli/wiki/generate]
,ビルドして起動,ng serve
,ビルド,[ng build|https://github.com/angular/angular-cli/wiki/build]
,ユニットテスト,ng test
,E2Eテスト,mg e2e
,i118nメッセージを抽出,ng xi18n
,指定されたキーワードで検索,ng doc keyword
,TSLintによるコードチェック,ng lint
,現在の設定を取得,ng get key
,指定されたキー/値を設定,ng set key=value
,Angular CLIのバージョン,ng version
::ng generate サブコマンド
,要素,コマンド
,モジュール,ng g moduole hoge
,コンポーネント,ng g component hoge
,ディレクティブ,ng g directive hoge
,パイプ,ng g pipe hoge
,サービス,ng g service hoge
,ガード,ng g guard hoge
,クラス,ng g class hoge
,インターフェース,ng g interface hoge
,列挙,ng g enum hoge
!!!ngx-bootstrap
*https://valor-software.com/ngx-bootstrap
*BootstrapをAgularアプリケーションから利用
!!Angular-CLIから利用
*https://github.com/valor-software/ngx-bootstrap/blob/development/docs/getting-started/ng-cli.md
::インストール
npm install ngx-bootstrap bootstrap --save
::src/app/app.module.ts の編集
import { AlertModule } from 'ngx-bootstrap';
:
@NgModule({
:
imports: [AlertModule.forRoot(), ... ],
:
})
::.angular-cli.json に以下を追加
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
"styles.css"
],
:: src/app/app.component.html に以下を追加
hello
{{ref_image bootstrap_alert.jpg}}
!!!Angular Material
*https://material.angular.io/
!!!非同期通信
::app.module.ts
import { HttpModule } from '@angular/http';
:
@NgModule({
:
imports: [
:
HttpModule,
],
:
})
!!!データバインディング
!!構文
,データ方向,種類,記法
,コンポーネント -> ビュー,補間,{{...}}
,コンポーネント -> ビュー,プロパティ/属性バインディング,[property]='value'
,ビュー -> コンポーネント,イベントバインディング,(event)='handler'
,コンポーネント <-> ビュー,双方向バインディング,[(target)]='value'
!テンプレート参照変数
*#変数名
*(change)="0"は、イベントトリガーで値を更新するため必要
{{txtHoge.value}}
!!双方向バインディング
*import と @NgModule の imports に FormModuleを追加
::ルートモジュール(app.modules.ts)
import { FormsModule } from '@angular/forms';
:
@NgModule({
:
imports: [
BrowserModule,
FormsModule,
:
::ビュー
*input/textarea/selectなどフォーム要素をバインドするには、ngModel を利用する
*このためには、name属性の指定が必須
*ngModelを[(ngModel)]とする
::コンポーネント
export class AccountComponent implements OnInit {
testActions: string[] = ['','login','logout','check'];
selectedAction: string = '';
!入力値の加工
*上記は、プロパティバインディング、イベントバインディングを組み合わせて、双方向を実現している。
*データバインディング時に値を加工する場合、[(ngModel)] を [ngModel]と(ngModelChagen) に分解
*$eventは入力値そのものを表す
!!!ルーティング
*https://qiita.com/kazukisugita/items/5c683e93168505720e5f
!!適用
!プロジェクト作成
> ng new app --routing
::--routing オプションを付与せずにプロジェクトを作成した場合
*/src/app/app-routing.module.ts を追加
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [
RouterModule.forRoot(routes),
],
exports: [RouterModule]
})
export class AppRoutingModule { }
*/src/app/app.module.ts
import { AppRoutingModule } from './app-routing.module';
:
@NgModule({
imports: [
BrowserModule,
AppRoutingModule,
],
providers: [],
*/src/app/app.component.spec.ts
import { RouterTestingModule } from '@angular/router/testing';
:
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
!コンポーネント作成
> ng g component account --routing
!ルーティング定義
*app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AccountComponent } from './account/account.component'
const routes: Routes = [
{
path: 'account', component: AccountComponent
}
];
@NgModule({
imports: [
RouterModule.forRoot(routes),
],
exports: [RouterModule]
})
export class AppRoutingModule { }
!利用
Account
!!!コンポーネント
!!ライフサイクル
,ライフサイクル,内容
,コンポーネント生成,
,コンストラクター,
,ngOnChanges,@Input経由で入力値が設定/再設定された
,ngOnInit,入力値(@Inputp)が処理された後、コンポーネントの初期化時(最初のngOnChangesメソッドの後で一度だけ)
,ngDoCheck,状態の変更を検出したとき
,ngAfterContentInit,外部コンテンツを初期化した時(最初のngDoCheckメソッドの後で一度だけ)
,ngAfterContentChecked,外部コンテンツの変更をチェックした時
,ngAfterViewInit,現在のコンポーネントと子コンポーネントのビューを生成した時(最初のngAfterContentCheckedメソッドの後で一度だけ)
,ngAfterViewChecked,現在のコンポーネントと子コンポーネントのビューが変更された時
,ngOnDestroyed,コンポーネントが破棄される時
,コンポーネント破棄,
!!!サービス
*サービスクラスであることの条件は、@Injectable デコレータを付与することのみ。
*@Injectable デコレータは、コンポーネントに対してサービスを引き渡せることを意味する。
!!登録
*モジュールにサービスを登録する。
*コンポーネントにも登録できる。この場合コンポーネントと子コンポーネントのみで利用できる。
import { HogeService } from './hoge.service';
@NgModule({
:
providers: [HogeService],
:
})
!!依存性注入
*方法を宣言するのは、@NgModule/@Component デコレータの providersパラメータ
*サービスを提供するためのProviderオブジェクトを登録する
::Providerであることの条件は以下のプロパティを持つこと
,プロパティ,内容
,provide,サービスを注入する際に利用するDIトークン
,useXxxxx,サービスの生成方法 例 userClass: XXXX と指定するとクラス XXXX を常にnew でインスタンス化する
,multi,同一のDIトークンに対して複数のProviderを追加するか
!useXxxx
,プロパティ,内容
,useClass,指定されたクラスを注入のたびにインスタンス化
,useValue,指定されたオブジェクトを常に引き渡す(同じ値になる)
,useExisting,指定されたトークンのエイリアスを生成
,useFactory,指定されたファクトリー関数で注入の際にオブジェクトを生成
::useClass
*常に新たなインスタンスを生成する
providers: [
{ provide: HogeService, useClass: HogeService }
]
::useValue
*常に同じオブジェクトを注入する
*クラスのインスタンスを渡す
providers: [
{ provide: HogeService, useVlaue: new HogeService() }
]
::useExisting
*トークンのエイリアスを生成
providers: [
{ provide: HogeService, useClass: HogeService }、
{ provide: HogeAliasService, useExisting: HogeService }、
]
""互換性維持など、別のトークンから同一インスタンスを取得したい場合などに利用
::useFactory
*ファクトリー関数経由でインスタンスを生成
providers: [
{ provide: HogeService, useFactory: () => {
let service = new HogeService();
service.foo = "bar";
return service;
}
}
]
!!!Modules
!!Http
*https://angular.io/guide/http
!!!RxJs
!!コンポーネントからサービスのデータを購読する
*https://angular.io/guide/component-interaction#!#bidirectional-service
::Service
import { Subject } from 'rxjs/subject';
import { User } from './user';
@Injectable()
export class AccountService {
private userChangeAnnouncedSource = new Subject();
userChangeAnnounced$ = this.userChangeAnnouncedSource.asObservable();
:
announceUserChange(user: User) {
this.userChangeAnnouncedSource.next(user);
}
:
::Component
import { Subscription } from 'rxjs/Subscription';
export class AccountComponent implements OnInit, OnDestroy {
user: User;
subscription: Subscription
ngOnInit() {
this.subscription = this.accountService.userChangeAnnounced$.subscribe((user:User) => {
this.user = user;
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
:
!!!UI
!!Angular Material
*https://material.angular.io/
!レスポンシブレイアウト
*https://material.angular.io/cdk/layout/overview
!!!テスト
!!ユニットテスト
!Karma
*https://karma-runner.github.io/2.0/index.html
*karma.conf.js
!!!Tips
!!機能
!Chrome拡張機能
augury
{{ref_image chrome_extension.jpg}}
!Facebook SDK
*https://developers.facebook.com/docs/javascript
!Hello.js 認証をまとめるJavaScriptライブラリ
*http://adodson.com/hello.js/#scope
!!文法
!Javascriptのグローバルオブジェクトを利用
declare const hoge;
!!コード
!コードからルーティング
import { Router } from '@angular/router';
:
constructor(private router: Router) {}
:
this.router.navigate(['/hoge'])
!CSRF
*https://angular.io/api/common/http/HttpClientXsrfModule
*https://angular.io/guide/http
*[Angular + HttpClientXsrfModule + Flask で CSRF|http://typea.info/blg/glob/2018/01/angular-httpclientxsrfmodule-flask-csrf.html]
!!参照
*[Angular CLIでサブディレクトリにビルドする方法|http://apoc.jp/angular-cli-subdir/]