No.1773
06/03 08:34

edit

Angular Fullcalendar を使用する

● Angular Fullcalendar を使用する

● パッケージのインストール

npm install --save @fullcalendar/angular @fullcalendar/core @fullcalendar/daygrid @fullcalendar/interaction @fullcalendar/timegrid

styles.scss

// add this
@import '~@fullcalendar/core/main.css';
@import '~@fullcalendar/daygrid/main.css';
@import '~@fullcalendar/timegrid/main.css';

app/app.module.ts

// add
import { FullCalendarModule } from '@fullcalendar/angular';

......

  imports: [
    BrowserModule,
    FullCalendarModule // add
  ],

app/app.component.ts

// calendar
import { FullCalendarComponent } from '@fullcalendar/angular';
import { EventInput } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGrigPlugin from '@fullcalendar/timegrid';
import interactionPlugin from '@fullcalendar/interaction'; // for dateClick
export class AppComponent {

  @ViewChild('calendar') calendarComponent: FullCalendarComponent; // the #calendar in the template

  calendarVisible = true;
  calendarPlugins = [dayGridPlugin, timeGrigPlugin, interactionPlugin];
  calendarWeekends = true;
  calendarEvents: EventInput[] = [
    { title: 'Event Now', start: new Date() }
  ];

  toggleVisible() {
    this.calendarVisible = !this.calendarVisible;
  }

  toggleWeekends() {
    this.calendarWeekends = !this.calendarWeekends;
  }

  gotoPast() {
    let calendarApi = this.calendarComponent.getApi();
    calendarApi.gotoDate('2000-01-01'); // call a method on the Calendar object
  }

  handleDateClick(arg) {
    if (confirm('Would you like to add an event to ' + arg.dateStr + ' ?')) {
      this.calendarEvents = this.calendarEvents.concat({ // add new event data. must create new array
        title: 'New Event',
        start: arg.date,
        allDay: arg.allDay
      })
    }
  }

}

No.1763
05/25 16:29

edit

Angular アプリをサブディレクトリにビルド(デプロイ)する

● Angular アプリをサブディレクトリにビルド(デプロイ)する

通常ビルドする

ng build

サブディレクトリ /angular/ にビルドする

ng build --base-href=/angular/

(最後のスラッシュは忘れずに!)

No.1761
05/24 22:10

edit

No.1715
03/04 22:05

edit

Angular で datetimepicker を使用する

● Angular で datetimepicker を使用する

またバリデーションにも対応させます。


* jquery , jquery-datetimepicker をインストール

npm install jquery --save
npm install jquery-datetimepicker  --save

* angular.json に 追加

            "styles": [
              "src/styles.scss" ,
              "node_modules/jquery-datetimepicker/build/jquery.datetimepicker.min.css"
            ],
            "scripts": [
              "node_modules/jquery/dist/jquery.min.js" ,
              "node_modules/jquery-datetimepicker/build/jquery.datetimepicker.full.min.js"
            ]


* app/app.component.ts に追加

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

// jquery
declare var $: any;


* 表示するページ page01 を新規作成

ng g component page01

1.(ルーティング) * app/app-routing.module.ts にルーティングを追加

const routes: Routes = [
  { path: 'page01', component: Page01Component }, 
  { path: '**', component: Page01Component }, // 追加
];

2.(html) app/page01/page01.component.html を以下の内容で保存

<input type="text" class="form-control jquery-datetimepicker" name="test-date" formControlName="datepicker" autocomplete="off">
<pre class="debug">
{{ registerForm.value | json }} <br>
Validation: {{ registerForm.get( 'datepicker' ).valid }}
</pre>

3.(TypeScript) app/page01/page01.component.ts を以下の内容で保存

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

// jquery
declare var $: any;

@Component({
  selector: 'app-page01',
  templateUrl: './page01.component.html',
  styleUrls: ['./page01.component.scss']
})
export class Page01Component implements OnInit {
  constructor() { }
  ngOnInit() {

    // ===== jquery-datetimepicker =====
    let _this = this;
    $.datetimepicker.setLocale('ja'); // 日本語化
    $('input.jquery-datetimepicker').datetimepicker({
      lang: 'ja',
      timepicker: false,
      format:'Y-m-d',
      onSelectDate:function( date ){
        var year = date.getFullYear();
        var  month = ("0"+(date.getMonth() + 1)).slice(-2);
        var  date =  ("0"+date.getDate()).slice(-2);
        var date_formatted = year + '-' + month + '-' + date;
        _this.registerForm.get('datepicker').setValue( date_formatted );
      }
    });
    // ===== jquery-datetimepicker =====

  }
}

これでコンポーネントは完成です。

jquery-datetimepicker で日付を選択時に、_this.registerForm.get('datepicker') にも値が反映されます。

No.1708
02/21 15:36

edit

Angular コーディングスタイルガイドの日本語訳抜粋

● Angular コーディングスタイルガイドの日本語訳抜粋

https://www.miraclelinux.com/tech-blog/4cd30h

おすすめです。

No.1707
02/18 14:22

edit

Laravel6 に jwt-auth をインストールしAngular の SPAからログインする(フロントエンド Angular編)

● Angularアプリの作成

ng new jwtauth-app
cd jwtauth-app
ng serve --open

● 必要なコンポーネント、サービスの作成

ng g component login
ng g component home
ng g service services/authentication

● 必要なガードの作成

ng g guard guard/auth

( CanActivate を選択して作成する )

app/guard/auth.guard.ts

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthenticationService } from '../services/authentication.service';

@Injectable()
export class AuthGuard implements CanActivate {
	constructor(
		private authService: AuthenticationService,
		private router: Router
	) { }

	canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
		if ( !this.authService.isAuthenticated() ) {
			this.router.navigate(['login']);
			return false;
		}
		return true;
	}
}

作成したガードを app/app.module.ts へ読み込ませる
( import して @NgModuleのprovidersに追加する )

app/app.module.ts

// guard
import { AuthGuard } from './guard/auth.guard';

@NgModule({
    ........
	providers: [AuthGuard],
})

● 必要なモデルの作成

mkdir src/app/models
vi src/app/models/user.ts

user.ts

export class User {
    id: number;
    username: string;
    password: string;
    firstName: string;
    lastName: string;
    token?: string;
}
app/home/<いくつかのファイル>
app/login/<いくつかのファイル>
app/services/<いくつかのファイル>

が作成されます

● bootstrap4 を Angularアプリにインストール

npm install --save bootstrap jquery popper.js

angular.json に以下を追加

    "styles": [
      "src/styles.scss" ,
      "node_modules/bootstrap/dist/css/bootstrap.min.css"
    ],
    "scripts": [
      "node_modules/jquery/dist/jquery.slim.min.js",
      "node_modules/popper.js/dist/umd/popper.min.js",
      "node_modules/bootstrap/dist/js/bootstrap.min.js"
    ]

● auth0/angular-jwt のインストール

npm install @auth0/angular-jwt

● ReactiveFormsModule の読み込み

app/app.module.ts

import { ReactiveFormsModule } from '@angular/forms';

  imports: [
    ReactiveFormsModule ,    // 追加
  ],
No.1704
02/17 16:46

edit

「ERROR in node_modules/rxjs/internal/types.d.ts(81,44): error TS1005: ';' expected.」エラーの対処法

● 「ERROR in node_modules/rxjs/internal/types.d.ts(81,44): error TS1005: ';' expected.」エラーの対処法

rxjs": "^6.0.0",

 ↓

rxjs": "6.0.0",
No.1706
02/17 10:44

edit

No.1701
02/13 15:38

edit

angular/router ルーターのルート一覧を表示させる

● Augury を使用する

https://chrome.google.com/webstore/detail/augury/elgalmkoelokbchhkhacckoklkejnhcd?hl=ja

● 手動でルート一覧を表示させる

http://bit.ly/2UKeBDD

import { Router, Route } from "@angular/router";

constructor(private router: Router) { }

ngOnInit() {
  this.printpath('', this.router.config);
}

printpath(parent: String, config: Route[]) {
  for (let i = 0; i < config.length; i++) {
    const route = config[i];
    console.log(parent + '/' + route.path);
    if (route.children) {
      const currentPath = route.path ? parent + '/' + route.path : parent;
      this.printpath(currentPath, route.children);
    }
  }
}
No.1699
02/13 14:26

edit

Angular do not found

Finally, I am able to solve that issue.
do() is replaced by tap().
for reference https://www.academind.com/learn/javascript/rxjs-6-what-changed/
and tap() should be inside .pipe().
like this, .pipe(tap())
for more reference, you can refer this link,
https://alligator.io/angular/angular-6/
and
https://www.learnrxjs.io/operators/utility/do.html

http://bit.ly/31LeglK

import { of } from 'rxjs';
import { tap, map } from 'rxjs/operators';
No.1698
02/12 16:01

edit

ionic で 横スクロールするナビゲーション

● ionic で 横スクロールするナビゲーション

<ion-content overflow-scroll="true">
......
</ion-content>

http://bit.ly/2H6NKK1
http://bit.ly/2H5gB1h

No.1695
02/08 22:37

edit

angular/router で 前のページURLを取得する

import { Router, NavigationEnd } from '@angular/router';
	constructor(
		private router: Router
	) {
		// 前のページURLを取得する
		this.currentUrl = this.router.url;
		router.events.subscribe(event => {
			if (event instanceof NavigationEnd) {
				this.previousUrl = this.currentUrl;
				this.currentUrl = event.url;
			}
		});
	}

これで this.previousUrl に前ページURLが入ります。

引用: http://bit.ly/31DcnHM

No.1694
02/08 20:54

edit

Ionic で Firebase ( Cloud Firestore ) を使用する

● angularfire2 のインストール

npm install angularfire2 firebase

● FirebaseのWEBコンソール画面からアプリを登録して設定情報をコピーしておく

var config = {
  apiKey: 'Your credentials here',
  authDomain: 'Your credentials here',
  databaseURL: 'Your credentials here',
  projectId: 'Your credentials here',
  storageBucket: 'Your credentials here',
  messagingSenderId: 'Your credentials here'
};

● モデル(インターフェース)の定義

app/models/song.interface.ts

export interface Song {
    id: string;
    albumName: string;
    artistName: string;
    songDescription: string;
    sonName: string;
}

● モデル(サービス)の定義

Cloud Firestore のコレクション songList を操作するサービスを記述します。

ionic generate service services/data/firestore

自動生成された app/services/data/firestore.service.ts に以下を追記

import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Song } from '../../models/song.interface';
export class FirestoreService {
	constructor(public firestore: AngularFirestore) { }
	createSong(
		albumName: string,
		artistName: string,
		songDescription: string,
		songName: string
	): Promise<void> {
		const id = this.firestore.createId();
		return this.firestore.doc(`songList/${id}`).set({
			id,
			albumName,
			artistName,
			songDescription,
			songName,
		});
	}
	getSongList(): AngularFirestoreCollection<Song> {
		return this.firestore.collection(`songList`);
	}
	getSongDetail(songId: string): AngularFirestoreDocument<Song> {
		return this.firestore.collection('songList').doc(songId);
	}
	deleteSong(songId: string): Promise<void> {
		return this.firestore.doc(`songList/${songId}`).delete();
	}
}

● /home 画面にデータ一覧を表示

app/home/home.page.ts に下記を追加

import { FirestoreService } from '../services/data/firestore.service';
import { Router } from '@angular/router';
export class HomePage {
	public songList;  // add this
	constructor(
		private firestoreService: FirestoreService,
		private router: Router
	) { }
	ngOnInit() {
		this.songList = this.firestoreService.getSongList().valueChanges();  // add this
	}
}

app/home/home.page.html に下記を追加

<ion-content class="ion-padding">
	<ion-card *ngFor="let song of songList | async" routerLink="/detail/{{song.id}}">
		<ion-card-header>
			{{ song.songName }}
		</ion-card-header>
		<ion-card-content>
			Artist Name: {{ song.artistName }}
		</ion-card-content>
	</ion-card>
</ion-content>

● ルール設定(セキュリティ設定)を行う

セキュリティ設定をしていない場合は、全てのアクセスが却下となります。 また一番ゆるく(全てを許可)すると、誰でもアクセスできるようになります。

*1. 誰でもアクセスできる設定

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

この設定

export var firebaseConfig = {
    projectId: "my-project-name",
    storageBucket: "my-project-name.appspot.com",
};

だけで、誰でもアクセスできてしまいます。

*2. コレクション「songList」内なら誰でもアクセスできる設定

service cloud.firestore {
  match /databases/{database}/documents {
    match /songList/{songId} {
      allow read, write: if true;
    }
  }
}
なお {songId} は ワイルドカードです。
* と記述したいところですが、{songId}と書きます。
{songListId}でもいいみたいです。(文字列はなんでも良いらしい)

引用: http://bit.ly/2Om37Cz
http://bit.ly/385JJBi

No.1687
02/03 21:47

edit

Angular CLI からアプリの作成

● Angular CLI のインストール

npm install -g @angular/cli

● Angular CLI からアプリの作成

ng new myapp

● アプリの実行

ng serve --open
No.1683
05/21 22:57

edit

ionic で フォームバリデーションを作成する

● フォーム画面 /form/ に フォームバリデーションを作成する

* 1. app/form/form.page.ts へ記述

(モジュールの読み込み)
app/form/form.page.ts

// add
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';

(エラーメッセージの定義)
app/form/form.page.ts

	validations = {
		'username': [
			{ type: 'required', message: 'お名前は入力必須です' },
		],
		'email': [
			{ type: 'required', message: 'メールアドレスは入力必須です' },
		],
		'content': [
			{ type: 'required', message: 'お問い合わせ内容は入力必須です' },
		],
	};

(バリデーションフォームの定義)
app/form/form.page.ts

	public loginForm: FormGroup;

	constructor(
		public router: Router, 
		public formBuilder: FormBuilder) {

		this.loginForm = new FormGroup({
			username: new FormControl('', Validators.compose([
				Validators.required
			])),
			email: new FormControl('', Validators.compose([
				Validators.required
			])),
			content: new FormControl('', Validators.compose([
				Validators.required
			])),
		});
	}

* 2. app/form/form.page.html へ記述

(お名前フォームのみ)複数入力フォームがある場合は適宜追加すること

<form [formGroup]="loginForm">
    <ion-item>
        <ion-label position="stacked">お名前 <ion-text color="danger">*</ion-text></ion-label>
        <ion-input type="text" formControlName="username"></ion-input>

        <!-- error message -->
        <div class="error-container">
            <ng-container *ngFor="let validation of validations.username">
                <div class="error-message"
                    *ngIf="loginForm.get('username').hasError(validation.type) && (loginForm.get('username').dirty || loginForm.get('username').touched)">
                    <ion-icon name="information-circle-outline" color="danger"></ion-icon>
                    <ion-text color="danger">{{ validation.message }}</ion-text>
                </div>
            </ng-container>
        </div>
        <!-- /error message -->

    </ion-item>

	<div class="ion-padding">
		<ion-button [disabled]="!loginForm.valid" (click)="onClickSubmit()" expand="block" type="submit"
			class="ion-no-margin">送信する</ion-button>
	</div>

</form>

参考 : http://bit.ly/2RkXiXS

No.1680
01/24 19:17

edit

ionic で 次のページへリンクする / 遷移したページに戻るボタンをつける

https://localhost/posts/https://localhost/posts-show/123 への画面遷移を考えてみます。

* 1. posts-show ページの作成

ionic generate page posts-show

* 2. ルーティング posts-show/123 を受けれるようにする

app/posts-show/posts-show-routing.module.ts

const routes: Routes = [
  {
    path: ':postId',  // ● 引数を受ける変数を追加
    component: PostsShowPage
  }
];

* 3. posts.page.html からリンクを貼る。 app/posts/posts.page.ts に登録する。

app/posts/posts.page.html

	<ion-button expand="block" routerLink="/posts-show/" routerDirection="forward">詳細ページ1</ion-button>

* 4. posts-show ページに戻るボタンをつける

app/posts-show/posts-show.page.html

<ion-header>
	<ion-toolbar>
		// ● 追加 ↓
		<ion-buttons slot="start">
		    	<ion-back-button defaultHref="/posts"></ion-back-button>
		</ion-buttons>
		// ● 追加 ↑
		<ion-title>posts-show</ion-title>
	</ion-toolbar>
</ion-header>

デフォルトのリンク先(/posts)をつけておきます。
https://ionicframework.com/jp/docs/api/back-button

No.1679
01/24 13:29

edit

ionic の 表示イベント(ライフサイクル)

● Ionicの Page Life Cycle

https://ionicframework.com/jp/docs/angular/lifecycle

* 1. AngularのLife Cycle Events

Event Name Description
ngOnInit コンポーネントの初期化中に発生します。このイベントを使用して、ローカルメンバーを初期化し、一度だけ実行する必要があるServiceを呼び出すことができます。
ngOnDestroy Angularがビューを破棄する直前に発生します。 observables の unsubscribe などのクリーンアップに役立ちます。

* 2. IonicのPage Events

Event Name Description
ionViewWillEnter コンポーネントが表示されるアニメーションがはじまる時に発火します。
ionViewDidEnter コンポーネントが表示されるアニメーションが終了した時に発火します。
ionViewWillLeave コンポーネントを離脱するアニメーションがはじまる時に発火します。
ionViewDidLeave コンポーネントを離脱するアニメーションが終了した時に発火します。
No.1677
01/23 18:31

edit

ionic で now loading のインジケーターを表示させる

● ion-loading

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

app/posts/posts.page.ts

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

constructor に 以下のloadingController を追加

	constructor(
		private http: HttpClient, 
		public loadingController: LoadingController  // この行を追加
	) { }

以下を追加


	async ionViewDidEnter(){
		// define loading
		const loading = await this.loadingController.create({
			spinner: 'circular',
			message: 'loading ...',
			translucent: true,
		});
		// loading 表示
		await loading.present();

		// Make the HTTP request:
		this.http.get('https://YOUR-SERVER.TLD/api/posts').subscribe(data => {
			console.log(data);
			loading.dismiss();  // これを追加(jsonデータ完了時に loading を非表示とする)
		});
	}

No.1676
01/23 18:32

edit

No.1674
01/22 17:30

edit

ionic の 問い合わせフォームを作成する

● まずは一番シンプルなフォームを作成する

app/form/form.page.html

	<form #form="ngForm" (ngSubmit)="postForm(form.value)">
		<ion-item>
			<ion-label position="stacked">お名前 <ion-text color="danger">*</ion-text></ion-label>
			<ion-input type="text" [(ngModel)]="contact.username" name="contact.username"></ion-input>
		</ion-item>

		<ion-item>
			<ion-label position="stacked">メールアドレス <ion-text color="danger">*</ion-text></ion-label>
			<ion-input required email type="email" [(ngModel)]="contact.email" name="contact.email"></ion-input>
		</ion-item>

		<ion-item>
			<ion-label position="stacked">お問い合わせ内容 <ion-text color="danger">*</ion-text></ion-label>
			<ion-textarea [(ngModel)]="contact.content" name="contact.content"></ion-textarea>
		</ion-item>

		<div class="ion-padding">
			<ion-button expand="block" type="submit" class="ion-no-margin">送信する</ion-button>
		</div>
	</form>

app/form/form.page.ts

export class FormPage implements OnInit {

	// フォームパラメーターモデルの定義
	contact = {
		username: '' ,
		email: '' ,
		content: '',
	};

	constructor() {}
	ngOnInit() {}

	postForm(formValue){
		console.log('postForm()');
		console.log( formValue );
	}

}
No.1673
01/22 17:01

edit

No.1672
01/22 14:41

edit

ionic の html で for ループで回す

● ionic の html で for ループで回す

* .ts ファイルで プロパティを宣言

app/posts/posts.page.ts

export class PostsPage implements OnInit {
	posts_loop : {};

	ngOnInit(): void {
                posts_loop = {};
        }

* .html ファイルで ループを回す

app/posts/posts.page.html

	<ion-item *ngFor="let v of posts_loop;">
			<img src="{{v.file_url_array['0']}}" />
	</ion-item>
No.1670
01/21 21:33

edit

ionic の HttpClientModule で サーバの json を読み込む

● 1. モジュール HttpClientModule の登録

app/app.module.ts

// ● Add this
import { HttpClientModule } from '@angular/common/http';

  imports: [
    BrowserModule,
    HttpClientModule, // ● Add this
    ..... ,
    ..... ,

● 2. 各ページで使用する

例 (app/posts/posts.page.ts)

app/posts/posts.page.ts


// ● Add this
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';

....
....
        // ● Add this
	constructor(private http: HttpClient) { }

        // ● Add this
	ngOnInit(): void {
		// Make the HTTP request:
		this.http.get('https://YOUR-SERVER.TLD/api/posts').subscribe(data => {
			console.log(data);
			console.log(data[1]['name']);
		});
	}

No.1668
01/21 21:33

edit

ionic で画面を追加する

● ionic generate

ionic generate <type> <name> [options]

コマンド例

ionic generate
ionic generate page
ionic generate page contact
ionic generate component contact/form
ionic generate component login-form --change-detection=OnPush
ionic generate directive ripple --skip-import
ionic generate service api/user

実際の例

(posts ページを追加してみます。)(フォルダも作成できます。その場合は posts/index のように記述します。)

ionic generate page posts

こちらのファイルが追加されます

CREATE src/app/posts/posts-routing.module.ts (343 bytes)
CREATE src/app/posts/posts.module.ts (465 bytes)
CREATE src/app/posts/posts.page.scss (0 bytes)
CREATE src/app/posts/posts.page.html (124 bytes)
CREATE src/app/posts/posts.page.spec.ts (640 bytes)
CREATE src/app/posts/posts.page.ts (252 bytes)
UPDATE src/app/app-routing.module.ts (712 bytes)

1. サイドメニューにページを追加する

app/app.component.ts

  public appPages = [
    {
      title: 'Home',
      url: '/home',
      icon: 'home'
    },
    {
      title: 'List',
      url: '/list',
      icon: 'list'
    },
// 追加
    {
      title: 'Posts',
      url: '/posts',
      icon: 'clipboard'
    },
// 追加
  ];

icon はこちらから調べます
https://ionicons.com/

これで、サイドメニューに追加されて画面遷移が確認できます。

追加されたページに sidemenu を追加する

app/posts/posts.page.html

<ion-header>
	<ion-toolbar>
		<ion-title>posts</ion-title>
	</ion-toolbar>
</ion-header>

<ion-header>
	<ion-toolbar>
		<ion-buttons slot="start">
			<ion-menu-button></ion-menu-button>
		</ion-buttons>
		<ion-title>
			posts
		</ion-title>
	</ion-toolbar>
</ion-header>
No.1665
01/23 09:57

edit

No.1664
01/21 14:39

edit

ionicのはじめ方

● ionic の インストール

npm i -g ionic cordova

● ionic アプリの新規作成

Angular 4+ w/ Angular CLI

ionic start myapp

または
Angular 2/3 w/ @ionic/app-scripts

ionic start myapp --type=ionic-angular

ionic-angular のところは プロジェクトのタイプ を選択します。

Project Type Description
angular Ionic Angular 4+ w/ Angular CLI for Tooling
ionic-angular Ionic Angular 2/3 w/ @ionic/app-scripts for Tooling
ionic1 Ionic 1 w/ AngularJS

テンプレートの選択

 Starter template: (Use arrow keys)
❯ tabs     | A starting project with a simple tabbed interface 
  sidemenu | A starting project with a side menu with navigation in the content area 
  blank    | A blank starter project 
  super    | A starting project complete with pre-built pages, providers and best practices for Ionic development. 
  tutorial | A tutorial based project that goes along with the Ionic documentation 
  aws      | AWS Mobile Hub Starter 

● ionic アプリの起動

cd myapp
ionic serve --devapp

● 実機(iPhone , Android , iPad)で確認

ionic devapp をインストールします
https://ionicframework.com/docs/appflow/devapp

● チュートリアル

https://ionicframework.com/jp/docs/angular/your-first-app

● ionicをビルドしてWEBサーバへデプロイする

ionic build

www フォルダをアップロードすれば普通に動きます。

● ionic のバージョン確認

ionic info

--type=ionic-angular で作成したアプリの場合

Ionic:
   Ionic CLI          : 5.4.13 (/Users/kato/.anyenv/envs/nodenv/versions/12.14.0/lib/node_modules/ionic)
   Ionic Framework    : ionic-angular 3.9.9
   @ionic/app-scripts : 3.2.4

Utility:
   cordova-res : 0.8.1
   native-run  : not installed

System:
   NodeJS : v12.14.0 (/Users/kato/.anyenv/envs/nodenv/versions/12.14.0/bin/node)
   npm    : 6.13.4
   OS     : macOS Catalina

ionic4アプリの場合

Ionic:
   Ionic CLI                     : 5.4.13 (/Users/kato/.anyenv/envs/nodenv/versions/12.14.0/lib/node_modules/ionic)
   Ionic Framework               : @ionic/angular 4.11.7
   @angular-devkit/build-angular : 0.801.3
   @angular-devkit/schematics    : 8.1.3
   @angular/cli                  : 8.1.3
   @ionic/angular-toolkit        : 2.1.1

Cordova:
   Cordova CLI       : 9.0.0 (cordova-lib@9.0.1)
   Cordova Platforms : not available
   Cordova Plugins   : not available

Utility:
   cordova-res : 0.8.1
   native-run  : not installed

System:
   NodeJS : v12.14.0 (/Users/kato/.anyenv/envs/nodenv/versions/12.14.0/bin/node)
   npm    : 6.13.4
   OS     : macOS Catalina
No.1650
01/08 19:42

edit