スポンサーリンク

Ionicで作る モバイルアプリ制作入門[Angular版]を写経してTODOアプリを作成する

2020年4月11日

以下の本をほぼ写経して、TODOアプリを作成してみたいと思います。

Ionic5のstarter templatesには、以下の4つ + alpha があります。

  • blank
  • list
  • sidemenu
  • tabs
ionic startしたときに出てくるStarter templates

Ionicで作る モバイルアプリ制作入門[Angular版] では、sidemenu テンプレートを用いてTODOアプリを作成する手順が記載されています。それをほぼ写経して、tabs テンプレートを用いて、TODOアプリを作成したいと思います。

スポンサーリンク

ソースコードとDEMOサイト

ソースコード
https://github.com/adash333/ionic5-localStorage-todo
DEMOサイト
https://sharp-poincare-84715e.netlify.com/

開発環境

Windows 10 Pro
Chrome
VisualStudioCode 1.43.2
git version 2.20.1.windows.1
nvm 1.1.7
Android Studio 3.5
node 13.12.0
npm 6.14.4
yarn 1.22.4
@ionic/cli 6.3.0
@ionic/angular 5.0.7
@angular/cli 8.3.25

Ionic5の環境構築については以下をご覧ください。

新規Ionic5アプリの作成

C:/ionic/ フォルダをVisualStudioCodeで開き、Ctrl+@でターミナル画面を開き、以下を入力します。

ionic start

その後は、以下のように選んでいきます。6分くらいかかり、全部で

? Framework: Angular
? Project name: ionic5-localStorage-todo
? Starter template: tabs
? Integrate your new app with Capacitor to target native iOS and Android? No

開発サーバを起動します。

cd ionic5-localStorage-todo
ionic serve

自動的にChromeが開いて、以下のようになります。私の場合は、Windowsをdarkモードにしているので画面が真っ黒ですが、通常は白い画面が出てきます。

Ctrl +C => y + Enter で開発サーバが停止しますが、まずは、開発サーバを起動したまま、 src/ フォルダ内のコードを編集・保存して画面が自動的に変化するのを確認していきます。

ion-inputとion-list

Todoの入力欄と、 Todoリスト を描画します。

src/app/tab1/tab1.page.html

(変更前)

(変更後)

なんか、<ion-title></ion-title>が、<ion-header>の中だけでなく、<ion-content>の中にも登場していてややこしい(これはIonic4までは無かった)ですが、以下の解説を見ると、iOSの”Collapsible Large Titles” のためのものらしいです。iOSはよくわかりません。WEBアプリを作りたいので、気にせず、<ion-header>の中だけ変更すればよさそうです。

https://ionicframework.com/jp/docs/api/title#collapsible-large-titles

https://ionicframework.com/docs/api/input

https://ionicframework.com/docs/api/list

変数のバインディング

Angularに特徴的な {{ }} のカッコを用いて、tab1.page.ts で定義した変数を、tab1.page.html で表示するようにします。ページタイトルと、TODOリストを {{ }} の記法を用いて書き直します。

src/app/tab1/tab1.page.ts

(変更前)

(変更後)

src/app/tab1/tab1.page.html

(変更前)

(変更後)

*ngFor=”let t of todos”

の書き方は、Angularに特徴的です。

Inputのバインディング

tab1.page.html のInputに入力した値をtab1.page.tsで受け取り(ビュー からデータへ)、またTODOリストに表示(データからビューへ)させたいので、双方向データバインディングの表記を用います。

出典: https://angular.io/guide/template-syntax

参考: https://medium.com/@chameeradulanga87/one-way-and-two-way-data-binding-in-angular-dad3d933eb68

src/app/tab1/tab1.page.ts  (変更後)

src/app/tab1/tab1.page.html (変更後)

画面内のInputフォームに、タスク5 と入力して、『追加』をクリックすると、以下のようになります。

localStorageを用いてデータを永続化

今のままだと、ブラウザをリロードすると、タスク5 が消えてしまいます。これをWEBブラウザに保存しておく方法として、Web Storageというものがあります。

localStorageの使い方

JSON.stringify() 関数は、()の中身である配列を、JSON文字列に変換する関数らしいです。

逆は、JSON.parse() 関数であり、JSON文字列を、javascriptの配列に変換する関数らしいです。

ということで、以下のように変更します。

src/app/tab1/tab1.page.ts  (変更後)

src/app/tab1/tab1.page.html  はこのままで、データがlocalStorageに永続化して保存されます。リロードしても、データは残ります。

localStorageについて

値のバリデーション

現時点では、タスクが空欄でも追加ボタンをクリックすると、空文字のタスクが追加されてしまいます。そこで、今回は、「必須入力」「3文字以上、20文字以下」を満たしたときのみ、追加ボタンをクリックできるようにします。

Angularの、”ngForm”を利用します。とりあえず、使い方はコードを見て、覚えるしか無さそうです。

参考:テンプレート駆動バリデーション

src/app/tab1/tab1.page.html

tabs/tabs.page.htmlを編集して下のタブ選択欄を変更

(変更前)

(変更後)

アイコンについては、 https://ionicons.com/ から選ぶことができます。

タスク追加をtab2.page.htmlに移動する

src/app/tab2/tab2.page.html

src/app/tab2/tab2.page.ts

src/app/tab1/tab1.page.html

ion-action-sheetを用いてタスクの変更・削除を実装する

ion-action-sheet の公式ドキュメントを見ます。

このソースコードをコピペしながら、タスクの『編集』と『削除』を実装してみます。

import { ActionSheetController } from '@ionic/angular';

constructor(public actionSheetController: ActionSheetController) {}

は必要そうなので、 src/app/tab1/tab1.page.ts  にそのままコピペします。

さらに、changeTodo() という関数を作っていきます。

src/app/tab1/tab1.page.ts

src/app/tab1/tab1.page.html

あれ、閉じるのアイコンが表示されません。icon を間違えて、 cancel と書いてしまっていました。正しくは close でしたので修正。

タスクの削除を実装

*ngFor に

let i = index

を追加し、changeTodo()関数に引数をつけて

changeTodo(i)

とします。

src/app/tab1/tab1.page.html

src/app/tab1/tab1.page.ts

ちゃんと削除できました

ここまでのソースコード
https://github.com/adash333/ionic5-localStorage-todo/tree/c8269fe84e42a44bae13375cb45b045649a89d03

タスクの変更を実装する

タスクの変更は、ion-action-sheet の『編集』をクリックすると、Inputの付いたPromptタイプのアラート(ion-alert)を表示し、それを利用して編集を行えるようにします。

https://ionicframework.com/jp/docs/api/alert

src/app/tab1/tab1.page.ts

今回も、以下のように記載します。

import { AlertController } from '@ionic/angular';

constructor(public alertController: AlertController) {}

src/app/tab1/tab1.page.ts

これで編集ができるようになりました。

画像はsrc/assets/images/ フォルダに保存か?

Tab3を編集してみます。cardを表示してみたいと思います。

https://ionicframework.com/jp/docs/api/card

Pixabayから画像をダウンロードします。
https://pixabay.com/ja/photos/%E6%97%A5%E3%81%AE%E5%87%BA-%E6%B0%B4-%E5%A4%9C%E6%98%8E%E3%81%91-%E6%9C%9D-%E9%A2%A8%E6%99%AF-4987384/

そして、src/assets/images/ フォルダを作成し、その中に、先ほどダウンロードした画像をsunrise.jpg という名前で保存します。

この画像は、

<img src="assets/images/sunrise.jpg">

で表示することができるそうです。


      <ion-card>
        <img src="assets/images/sunrise.jpg" />
        <ion-card-header>
          <ion-card-subtitle>Destination</ion-card-subtitle>
          <ion-card-title>Madison, WI</ion-card-title>
        </ion-card-header>
        <ion-card-content>
          Founded in 1829 on an isthmus between Lake Monona and Lake Mendota, Madison was named the capital of the Wisconsin Territory in 1836.
        </ion-card-content>
      </ion-card>
 

この後、ちょこっと文章を変えたりしました。

ソースコード
https://github.com/adash333/ionic5-localStorage-todo/tree/2b99140a940db1c9476f0bae09bb35548c1abfe3

Netlifyにデプロイ

以下を参考に、Netlifyにデプロイします。

https://www.netlify.com/ にログインして、画面右上の、”New site from Git” をクリック し、その後、先ほどの、ionic5-localStorage-todo を選択します。

Build Commandは、

npm run build -- --prod && echo '/* /index.html 200' >> www/_redirects

public directoryは、

www/

以下のようなエラーが出ます。

package.jsonの変更

package.jsonの”dependencies”: { } の中に、以下を追加します。

"@babel/compat-data": "7.8.0"

その後、ターミナル画面で以下を入力します。

npm install

git add .
git commit -m "@babel/compat-data"
git push

すると、Netlifyの方で、再度、自動的にDeployが始まります。

うまくいきました。以下のようになりました。
https://sharp-poincare-84715e.netlify.com/

ソースコードとDEMOサイト

ソースコード
https://github.com/adash333/ionic5-localStorage-todo

DEMOサイト
https://sharp-poincare-84715e.netlify.com/

Ionicのstarter templateに関するリンク

https://github.com/ionic-team/starters/tree/master/angular/official

https://ionicframework.com/docs/cli/commands/start

https://qiita.com/umi_mori/items/15dcfbe706ce081239ab

Angularのデータバインディングについて