はじめに
この記事は、最近フロントエンドでIonicを触る案件に参画したので、
簡単なTODOアプリを作成するために、大事そうなことをメモしたものをまとめたものです。
TODOアプリのリポジトリ
デフォルトで表示するページを指定する
「selectedIndex=""」を使うと、指定したIndexがデフォルトページとして設定できる。
Index指定なので、0が一番最初のページ。
devサーバーを動かす
$ cd プロジェクトディレクトリ
$ ionic serve
ionicのプロジェクトを作成する
ionic start プロジェクト名 テンプレート名
componentの追加
pageディレクトリ配下に、作成したいコンポーネントのディレクトリを作る
mkdir -p page/component_name
app.module.tsにコンポーネントを登録する
※Ionicでは、フォルダ内にファイルを置くだけでは、使用できないので、
@NgModuleに追記する必要がある
import { HomePage } from '../pages/home/home'; // コンポーネントのインポート
import { LoginPage } from '../pages/login/login'; // コンポーネントのインポート
@NgModule({
declarations: [
MyApp,
HomePage,
LoginPage //ここにコンポーネントを追記する
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
LoginPage //ここにコンポーネントを追記する
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
コンポーネントをgenerateする
$ ionic g <component_name> <option>
オプション
--no-module #モジュールが作られない
参考サイト
Ionicで指定できるテンプレート
便利コマンド
ionic docs
リファレンスをターミナルから起動可能。
ionic info
プロジェクトの内部情報を出力する。
Yutas-MacBook-Air:ionic_tutorial ushijimayuuta$ ionic info
✔ Gathering environment info - done!
Ionic:
ionic (Ionic CLI) : 4.1.1 (/usr/local/lib/node_modules/ionic)
Ionic Framework : ionic-angular 3.9.2
@ionic/app-scripts : 3.2.0
Cordova:
cordova (Cordova CLI) : not installed
Cordova Platforms : not available
Cordova Plugins : not available
System:
NodeJS : v8.9.4 (/usr/local/bin/node)
npm : 6.2.0
OS : macOS High Sierra
hoge.module.tsの正体
このモジュールファイルは、遅延読み込み(Lazy Loading(以下LL))を実現するために存在している。
Ionicはindex.html
一つで全てのTSファイルを操作するので、LLしないとTypeScriptをJavaScriptをコンパイルする際に
ロードにすごく時間がかかり、UXが悪くなる。
hoge.module.tsを用意することで、実行が必要なときに読み込ませることができる。
ただし、LLを機能させるためには、二つの条件が必須
-
@component
の上に@IonicPage
を記述すること -
hoge.module.ts
のような、@Component
のファイル名にmoduleをつけたモジュールファイルを用意すること
なお、IonicではLLするページは文字列として表記する必要がある。
ただし、importやapp.module.tsへの追加は不要。
{ title: 'タスク一覧', component: 'TaskListPage' }
Ionicのオリジナルタグについて
アプリ表示タグ
<ion-app></ion-app>
#content
でion-navにcontentというネーミングをしている(要素参照のため)
swipeBackEnabled...スワイプを無効化
[root]...中身に何を表示するか決めるプロパティ(ここではrootPageを指定)
<ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>
サイドバーの表示
[content]プロパティにcontentを指定することで、メニューが表示されている間は、
contentがついているを右に押し出して表示する。
TypeScriptについて
pagesの型宣言(TypeScript)
title => string型
component => any型
pages: Array<{title: string, component: any}>;
this.pagesになっているのは、pagesがメソッドとして括られているため
これにより、サイドバーをデータバインディングしている
this.pages = [
{ title: 'Hello Ionic', component: HelloIonicPage },
{ title: 'My First List', component: ListPage }
];
メソッドの定義(ここでは、(click)で発火させるためのメソッドを定義している)
openPage(page) {
// close the menu when clicking a link from the menu
this.menu.close();
// navigate to the new page if it is not the current page
this.nav.setRoot(page.component);
}
Angularについて
*ngFor
...繰り返しを指示する構文(*ngFor="let <変数> of <展開する配列>")
let p of pages
...配列のpagesからpという名前で順番に値を取り出す
(click)
...onClickと同じ意味。ユーザーがクリックすると、指定したメソッド(ここではopenPage(p))が実行される。
(click)で発火するメソッドは、app.components.tsなどの各component.tsで定義する
<button ion-item *ngFor="let p of pages" (click)="openPage(p)">
<!--pの中のtitleを取り出す-->
{{p.title}}
</button>
配列の作り方
export class HelloIonicPage {
// string型のtitle変数を定義し、デフォルトの値を代入する
title: string = 'タスク登録';
// 配列tasksを用意し、オブジェクトにstring型のnameを格納
// nameをキーとしたオブジェクトの型が{ name: string } でそれを配列[]で格納
// 配列[]はArray<>でも表記可能
tasks: { name: string }[] = [
{ name: 'タスク1' },
{ name: 'タスク2' },
];
constructor() {
}
}
双方向でデータバインディングを行う
テンプレート側
[(ngModel)]="task" name="task"
TSファイル側
task: string;
バリデーションのやり方
- formタグの中で
#f="ngForm
とすることで、ローカル変数を定義する -
required
やminlength/maxlength
などを使ってバリデーションを定義 - submitの箇所で
[disabled]="!if.form.valid"
とすれば、条件に満たしてない場合にボタンがdisabledになる。
<ion-content padding>
<!--submitイベントが発生したときにaddTask()メソッドを呼び出す-->
<!--#f=ngFormによってHTMLテンプレート内で使うローカル変数の定義を行う-->
<form padding (submit)="addTask()" #f="ngForm">
<ion-list>
<ion-item>
<ion-label floating>タスク</ion-label>
<ion-input type="text" [(ngModel)]="task" name="task"
required minlength="3" maxlength="20"></ion-input>
</ion-item>
</ion-list>
<button type="submit" ion-button block [disabled]="!f.form.valid">追加</button>
</form>
<ion-list>
<ion-item *ngFor="let t of tasks">{{t.name}}</ion-item>
</ion-list>
</ion-content>