20190211のAngularJSに関する記事は5件です。

Angular framework features

As most of you already know, Angular is one of the most popular front-end JavaScript framework besides Vue.js and React. It has been around for past 10 years, and since then, it has gone through innumerable upgrades.

The first version of the framework was called AngularJS, which was launched in 2009. Though it was certainly not a perfect framework back then, mainly due to its large bundle size, performance issues, and other technical problems.
But that imperfection was the motivation behind the entire rewrite of the AngularJS.

Due to the not-at-all-perfect & failed attempt, the developers at Google decided to use really powerful libraries.

And not only that, but over time, they also added new features such as AOT (Ahead-of-Time) compiling, tree-shaking, and many other helpful features.
The next version – Angular 2 – was written in Typescript, which is a popular, typed superset of JavaScript introduced by Microsoft.

Typescript basically allowed Angular to show the errors in HTML templates. But, the main major feature which was added in the Angular 2 was a compiler that was deployed between written code and output shipped to the application.
This new compiler used to optimize the production of template-rendering, which further allowed the code to execute at the maximum speed in JVMs (JavaScript Virtual Machines).

The next version – Angular 4 – further saw view-engine enhancements and code generation reductions to build an app with less efforts and complexity.
Now, before you ask, the primary reason behind skipping the number 3 was mainly to avoid a confusion that was raised because of the misalignment of the router package’s version that was already distributed as version 3.3.0.
And within short period, they also released a minor upgrade – Angular version 4.3 – that featured HTTP Client, which is an easier-to-use library for creating HTTP requests.

After that, Angular 5 was released in November 2017, which followed the releases of Angular 2 and Angular 4 closely which were launched in September 2016 and March 2017 respectively.

The key feature of Angular 5 was the support for progressive web apps, and the main improvements included the enhancements in Material Design.
Angular version 6 was then released in May 2018 and was mainly focused on toolchain and making it simple to migrate quickly to Angular, instead of focusing on underlying framework.

The main updates in Angular 6 were ng update, Angular Material + CDK components, CLI Workspaces, Animations Performance Improvements, ng add, and Angular elements.
And now, Google has finally released the Angular 7 on 18th October 2018. And the main updates in the latest version of Angular are highlighted below.
And now, Google has finally released the Angular 7 on 18th October 2018.The Angular 7 version is primarily focused on the Ivy project, which has been going on since past release. The Ivy project is basically rewriting the Angular compiler and runtime code to make it better, faster, and smaller.

While the Ivy is still not ready for the prime time yet, but back in April, there were a lot of rumors & fake news about Ivy as well as many other features, which are now nowhere to be seen.

Source:

AngularJS training in chennai

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ネイティブアプリの緩やかな死とSPAのメリデメ比較

はじめに

タイトルは半分釣りですが、半分本気でそう考えています。
現在SPAでWebアプリを作る仕事をしていますが、遠くない未来、ネイティブアプリの時代は終わって、SPAで作られたWebアプリが主流になると思っています。
今回はネイティブアプリに変わるかもしれないSPAについて、具体的にどんなものか、ネイティブアプリと比較した場合のメリデメ等も考えていきたいと思います。

SPAとは何か?

SPAとは、SinglePageApplication(シングルページアプリケーション)の略称で、JavaScriptを使って、単一のページでコンテンツの切り替えを行う、Webアプリケーションを作る為の手法です。
私のポートフォリオサイトも、SPA(Nuxt.js)で作っています。
非同期通信を使って、ブラウザによるページ遷移を行わずに、コンテンツを切り替える事ができます。
裏側のHTMLはheadとCSSとJavaScriptしか存在せず、JavaScriptがDOMの切り替えを行なっています。

Pjaxと何が違うの?

少し話が脱線してしまいますが、非同期通信が出来るjQueryライブラリに、Pjaxというものがあります。
Pjaxは、URLを変更すると非同期でコンテンツを入れ替えてくれるライブラリで、SPAとは違い遷移先にページが存在しています(HTMLがある)。
SPAの場合、実際には遷移先にページが存在しておらず、JavaScriptでDOMとURLを動的に切り替えて、リクエストがあった差分のみを描画しています。

アプリ開発の現状

SPAは、非同期通信による滑らかな挙動、豊富なライブラリ、安全な認証等、ネイティブアプリと比較しても遜色ない環境が揃っていますが、まだ広く普及しているとは言い難いと思います。
裏側の管理画面や、単一ページをSPAで開発しているケースはありますが、アプリケーションそのものをSPAで開発しているプロダクトは、まだそう多くはないのではないでしょうか?
エンジニア的なコストはあまり詳しくはないですが、AWSやモジュール設計、セキュリティやパフォーマンスを意識した要件定義、およびコーディングが出来る人はそう多くありません。
デザイナー的にも、通常のWebアプリと同等の設計、つまりPC・タブレット・スマホ毎に設計が必要だったり、参考サイトやノウハウが少ない中での設計、ネイティブアプリと比べて足りないものを別のアプローチで補わないといけなかったりするので、要件定義や設計手法が手探りになる事が多いです。

SPAのメリット

ネイティブアプリと比較して、運用コストが低い

運用コストが低いというより、ネイティブアプリの運用コストが高すぎるのかもしれません。
後述する様にクロスプラットフォームである為、デバイスによって言語が違うということはありません。全てJavaScriptで動作するので、Webブラウザがあればすぐ使う事ができます。
デザインも、iOS・Androidで別に用意するという必要性はなく、またブラウザで動くアプリケーションなので、PCで使用する事も可能です。

ストアによる審査がない

Webアプリケーションなので、ネイティブアプリと違いストアによる審査が必要ありません。
プロダクトが完成したら、サーバーにプッシュして、デプロイするだけですぐに反映されます。リジェクトされる心配はありません。
また、ストアに支払う登録料も維持費も必要ありませんし、ストアによる高い決済手数料を気にする必要もありません。

ネイティブアプリに近い挙動を実現できる

SPAはJavaScriptを使って非同期によるページ遷移を行うので、ネイティブアプリに近い挙動を実現できます。
ネイティブアプリと完全に同じ事は出来ませんが、非同期による滑らかな体験は、従来のWebアプリケーションには無かった強力な武器となります。
データバインディングが出来るので、ネイティブアプリの様に、URLを変えずにタップしたら要素だけ変える、という様な事も可能です。

クロスプラットフォームである

SPAはブラウザで動くので、デバイスを選ばないクロスプラットフォームです。これもSPAの強力な武器となります。
基本的にネイティブアプリは、iOS / Androidで言語も開発チームも異なるので、チームは同じでも同時進行で開発する事はあまりないかと思います。
もちろん、ブラウザによる細かい挙動や仕様を考慮する必要性はありますが、iOS / Androidで同じプロダクトを別で作ることに比べたら、コストは微々たるものです。

豊富な開発環境

今ではネイティブアプリで使える環境が、SPAを使えばWebアプリケーションでも使える様になってきています。
例えば、私のサイトでも認証で使われているFirebase Authenticationは、ネイティブアプリでもWebでも使う事が出来ます。

SPAのデメリット

プッシュ通知が使えない

現状SPAの一番の課題になっているのは、このプッシュ通知が使えない事ではないでしょうか?
一応、WebPushという技術を使えば限定的に使う事はできますが、それでもiOS/Safariではサポートされておりませんので、必然的にiPhoneでは使えない事になります。
プッシュ通知が欲しい場合は、別のアプローチを試みる必要があります。

デザイナー・エンジニア共に経験者が少ない

SPAはまだ現状のアプリケーションの主流になりきれていないので、デザイナー・エンジニア共に経験者が少ないのが現状です。
業務ページ、単一ページをSPAで作成される事はあっても、プロダクトそのものにSPAが使われているケースは、国内ではまだ多くありません(海外の場合、Youtube・Google・JIRA等の前例はあります)。

高度なJavaScriptの技術が必要

正確にいうとデメリットではありませんが、SPAは今までサーバーサイドで行なっていた処理を、JavaScriptを使ってクライアントサイドで実行するので、必然的に高いJavaScriptの技術が必要になります。

SEO対策に注意が必要

現在はそうでもありませんが、SPAは裏側にHTMLが存在せず、JavaScriptを使って動的にDOMを切り替えるので、ほとんどがクローリングの対象外です。この問題を解決する為には、別途SEO対策をする必要があります。
Nuxt.jsであれば、modeを変更するだけで簡単にSEOで必要な要素を書き出してくれるので、現在ではあまり心配する必要はないかもしれません。

初期表示に時間がかかる

初期ページで必要なものを全て読み込む性質上、初期表示に時間がかかる事が多いです。

アナリティクスの設定が独特

慣れの問題なのですが、SPAでGoogleアナリティクスを導入する場合、公式から出ているライブラリを導入して、別途設定をする必要がある為、ネットによくある普通のサイトにアナリティクスを設定するやり方は、通用しない事がほとんどです。
また、通信が発生しない都合上通常のやり方ではイベントトラッキングが出来ないので、トラッキングさせるには、別途特殊な設定が必要だったりもします。

ジェスチャーが使えない

まだまだJavaScriptでは、ネイティブアプリの様な豊富なジェスチャーは使えないのが現状です。
ですが、ほとんどのジェスチャーはボタンアクションでサポート出来るので、あまり困る事もないですが。

ネイティブアプリのメリット

SPAのメリデメと反するものが多いですが、整理する為に改めて書いてみます。

プッシュ通知が使える

SPAと比較して、一番のメリットはこれではないでしょうか。
ネイティブアプリはプッシュ通知によるアプローチが出来るので、アプリはインストールしたけど使っていない様な休眠ユーザーを掘り起こしたり、PRしたいものを効率的にアプローチする事が出来ます。

ホーム画面に追加してもらえる

SPAとネイティブアプリで挙動が変わらないのであれば、インストールしてもらう事で生まれるメリットは、これではないでしょうか。
SPAでもホーム画面にアイコンを追加してもらう事は出来ますが、Androidはホーム画面にアイコンを追加する画面を出せるのでいいですが、iOSの場合はまだサポートされていませんので、ホーム画面に追加する場合、Safariから自分でやってもらうしか方法がありません。

ノウハウが豊富

ストアにネイティブアプリが豊富にあるので、参考事例を探すのに困る事はありません。

ジェスチャーが使える

ボタンアクションで賄えますが、表現が豊富であればアプローチできる幅が広がるので、ジェスチャーを使えるのは魅力的だと思います。

PCのデザインを作らなくていい

ネイティブアプリの場合スマホで動くので、PCのデザインを作らなくて良いのは、工数が一つ減ることになります。

ネイティブアプリのデメリット

運用コストがとてもかかる

これがネイティブアプリの一番のデメリットだと思います。
SPAが登場する以前は致し方なかったですが、SPAが出てきた今、Webアプリケーションとネイティブアプリの差異は、プッシュ通知以外ほぼ無いと言っても良いかもしれません。
そうなるとSPAと比較して、プラットフォームが異なるiOS/Androidでアプリを開発するのは、運用コストがもの凄くかかってきます。
ストアに支払う維持費や決済手数料もとても高いです。

インストールに時間がかかる

SPAの場合ネットに繋がないと使えませんが、裏を返せばそれは、インストールしなくてもページさえ開けば、すぐ使えるということです。
ネイティブアプリの場合インストールしないと使えないので、蓋を開けるまでどの様なアプリか分かりません。
よく分からないアプリを開く為に、わざわざインストールするでしょうか?
Webと違ってネイティブアプリの場合、広告を出してもその後「使ってもらう」為の工夫が必要なのです。

ストアの審査がある

ストアによる審査があるので、ネイティブアプリの場合本番に反映されるのが遅いです。

バージョン管理が大変

あまり詳しくは無いですが、アプリの場合バージョンを上げていかないとリジェクトされて更新が出来なくなるので、定期的にバージョンを上げていかないといけません。
SPAならサーバーにプッシュすればいいだけですが、アプリはそうもいかないみたいです。

まとめ

まとめますと、運用コストがめちゃくちゃかかるネイティブアプリより、今ならSPAで開発する方が遥かに効率的では?ということです。
SPAも開発コストがかかるので、ブログの様な直帰率が高いサービスにはオーバースペックかもしれませんが、滞在時間が長いアプリケーションにはとても適しています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Angular Material でテーマカラーをカスタマイズする方法

概要

Angular Material でテーマカラーを独自に設定する方法の備忘録。

前提

2019年1月1日時点の情報です。また、以下の環境になっている前提です。

  • Angular CLI: 7.0.6
  • Node.js: 10.15.0
  • npm: 6.4.1
  • Angular Material の導入が完了していること

Angular Material の導入方法については、「こちらの記事」を参考にしてください。

尚、テーマカラー変更方法について、公式リファレンスは「こちら

手順

アプリ全体の共通スタイルを定義するファイルに、以下のとおりに追記

src/styles.scss
/* ::::: テーマカラーのカスタマイズ ::::: */

// テーマ操作関数をライブラリからインポート
@import '~@angular/material/theming';

// Angular Material の共通スタイルをインクルード
@include mat-core();

// 色定義: オプションは hue カラーパレットで色コード指定, 参照: https://material.io/design/color/ and https://material.io/tools/color/
$my-app-primary: mat-palette($mat-light-blue, 800);
$my-app-accent:  mat-palette($mat-cyan, 600);
$my-app-warn:    mat-palette($mat-pink, 500, 900, A100);

// テーマとして色定義をまとめる
$my-app-theme: mat-light-theme($my-app-primary, $my-app-accent, $my-app-warn);

// カスタムテーマを適用
@include angular-material-theme($my-app-theme);

/* ::::: アプリ全体のスタイルを以下に指定 ::::: */

html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }

結果

アプリを起動してデザインを見てみる。

変更前

スクリーンショット 2019-02-11 11.27.05.png

変更後

スクリーンショット 2019-02-11 12.13.48.png

ちゃんと primary, accent, warn のカラーリングが変更された。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Angular Universal の Web サーバを Express でサクッと作る方法

概要

Angular Universal の Web サーバ部分を、簡単な疎通など確認するためにとりあえずサクッとコピペするための備忘録

前提

以下の必要なモジュールは、型定義ファイル(@types/* でインストール)含めインストールされていること

  • express
  • express-engine
  • @nguniversal/express-engine
  • @nguniversal/module-map-ngfactory-loader

Express で Web サーバを作成

以下の通り、Express を使って Web サーバを作成する

server/web-server.ts
// 以下の2インポートは最初に呼ばれる必要がある
import 'zone.js/dist/zone-node';
import 'reflect-metadata';

import * as express from 'express';
import { join } from 'path';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

const webServer = express();
const PORT = process.env.PORT || 3000;
const CLIENT_DIST_PATH = join(process.cwd(), 'dist/demo-app'); // TODO: パスをビルド先フォルダ名に合わせる
// 動的に生成される dist ファイルため、require() のままにしておく
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require(join(process.cwd(), 'dist/demo-app-server/main')); // TODO: パスをビルド先フォルダ名に合わせる

// テンプレートファイル名で拡張子が省略された場合のデフォルト拡張子を設定
webServer.set('view engine', 'html');
// テンプレートファイルを置くパスを設定
webServer.set('views', CLIENT_DIST_PATH);
// レンダリングに利用するテンプレートエンジンに Angular Express エンジン を登録
webServer.engine('html', ngExpressEngine({
  bootstrap: AppServerModuleNgFactory,
  providers: [ provideModuleMap(LAZY_MODULE_MAP) ]
}));
// サーバサイドレンダリングされる静的ファイル
webServer.get('*.*', express.static(CLIENT_DIST_PATH));

// 全ての API ルートは このルーティングを使用
webServer.use('/api/*', (req, res) => {
  console.log('[API が呼び出されました]');
  const response = { test1: 'aaa', test2: 'bbb' };
  res.status(200).send(response);
});

// 全ての通常ルートは Universal エンジンを使用
webServer.get('*', (req, res) => {
  console.log('[通常ルートが呼び出されました]');
  res.render('index', { req, res });
});

// Node サーバ開始
webServer.listen(PORT, () => {
  console.log(`Node server is listening - http://localhost:${PORT}`);
});

起動確認

起動スクリプト修正

以下のとおりに、package.json のスクリプトを修正

package.json
:
  "scripts": {
    "start": "node ./dist/server/web-server.js",
    "build": "npm run build:client && npm run build:server",
    "build:client": "ng run demo-app:app-shell:production",
    "build:server": "tsc --project server --outDir dist --allowjs true",
  },
:

以下のコマンドでビルド、アプリ起動

# ビルド
npm run build

# 起動
npm run start

以下の点をチェックし、問題なく動いていればOK。

  • ビルド完了後、以下のディレクトリと中身がルートディレクトリ配下に生成されているか
    • dist/common(クラサバ共用ファイル群)
    • dist/demo-app(クライアントのソースコード)
    • dist/demo-app-server(Universal 対応で作ったやつ)
    • dist/server(Express および API ロジック用ファイル群)
  • Web ブラウザにアクセスし、以下の挙動が行われるか
    • http://localhost:3000 でアクセスするとホーム画面が表示され、コンソールには [通常ルートが呼び出されました] と標準出力される
    • http://localhost:3000/api/aaa でアクセスすると、画面に {"test1":"aaa","test2":"bbb"} と表示され、コンソールには [API が呼び出されました] と標準出力される
    • http://localhost:3000/api でアクセスすると、URLは http://localhost:3000 となり、画面は何かしらの HTML で画面表示がなされ、コンソールには何かしらのエラーログが標準出力される(存在しないページへのアクセスエラー)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Angular7 で俺式 MEAN スタック Webアプリを構築する、ほぼ全手順(4)

概要

Angular7 で俺式 MEAN スタックを作るための備忘録。
今回は「DB接続部のロジック作成」を行う。

前提

2019年1月1日時点の情報です。また、以下の環境になっている前提です。

  • Angular CLI: 7.0.6
  • Node.js: 10.15.0
  • npm: 6.4.1

また、「Angular7 で俺式 MEAN スタック Webアプリを構築する、ほぼ全手順(3)」が完了していること。

事前準備

MongoDB を導入

今回は使用している環境が Mac なので Homebrew で入れます。導入方法は「こちらの Qiita 記事」を参照のこと。

もしくは、「MongoDBの公式サイト」からバイナリデータをダウンロードしてください。無料で落とせます。

ディレクトリ作成

以下の通りに、DB 操作用のディレクトリを作成しておく。

[ルートディレクトリ]
  :
  └─ server
     ├─ accessor # 新規作成: 外部接続用ディレクトリ
     │   └─ db
     │       ├─ model
     │       │   └─ sample.model.ts
     │       ├─ accessors
     │       │   └─ sample.accessor.ts
     │       └─ db.accessor.ts
     :

ゆくゆく Web API や、ファイルなどの他の外部接続を行うことも想定して、DB用に「db」というディレクトリで分けておく。

mongoose を導入

MongoDB を操作するパッケージをインストールする

# 本体パッケージ
npm i mongoose

# 型定義ファイル
npm i -D @types/mongoose

MongoDB のテストデータ投入

投入データの準備

DB: sample の特定のコレクションに投入するデータを事前に定義。
インポートに使用するのは mongoimport というコマンド。このコマンドがサポートしているファイル形式は「JSON」「CSV」「TSV」なので、今回は JSON ファイルでデータを以下のとおりに作成。

db-inputs/sample.json
[
  { "_id": 1, "name": "あああ", "age": 21 },
  { "_id": 2, "name": "いいい", "age": 22 },
  { "_id": 3, "name": "ううう", "age": 23 },
  { "_id": 4, "name": "えええ", "age": 24 },
  { "_id": 5, "name": "おおお", "age": 25 }
]

尚、投入データの順番は保証されないので、実行結果はドキュメントの順序がバラバラになる場合がある。

投入コマンド実行

準備ができたら、以下のコマンドでデータを投入する。

ポートはデフォルトの MongoDB ポート(27017) をリッスンしていると想定。
今回は、既存の該当するコレクション(RDB で言うとテーブル)を一回削除し、指定の JSON ファイルからデータを新規作成するコマンド。

また、認証設定が有効済みの想定なので、-u, -p, --authenticationDatabase オプションを末尾に付けている。(認証無効なら不要)

ルートディレクトリ直下で実行
mongoimport -h localhost:27017 --db sample --collection sample --drop --jsonArray --file db-inputs/sample.json -u admin -p Zaq12wsx --authenticationDatabase admin

オプションの詳細や他のコマンドは mongoimport --help 見れば書いてあリます。

結果確認

Mongo Compass で結果を見てみた。
以下のようになっていればOK.

スクリーンショット 2019-02-11 0.09.55.png

尚、MongoDB Compass の導入方法は、「こちらの記事」を参照のこと。

MongoDB 接続部作成

DB 接続基底クラス作成

server/accessor/db/db.accessor.ts
import { ConnectionOptions, createConnection, Connection } from 'mongoose';

/** DB アクセサ 基底クラス */
export class DbAccessor {

  /** DB 接続 */
  protected async createConnection(): Promise<Connection> {
    // TODO: 後々 config ファイルなどに移行
    const URI = 'mongodb://localhost:27017';
    const OPTIONS = {
      useNewUrlParser: true, // 推奨のパーサ設定記述
      dbName: 'sample', // 接続する DB
      user: 'admin', // 認証ユーザ ID
      pass: 'Zaq12wsx', // 認証パスワード
      auth: { authdb: 'admin'}, // 認証用 DB 指定
    } as ConnectionOptions;

    return await createConnection(URI, OPTIONS);

  }

}

モデル作成

モデルを定義するファイルを作成する

server/accessors/db/models/sample.model.ts
import { Document, Model, Schema, Connection } from 'mongoose';

const collectionName = 'sample';

/** サンプル ドキュメント */
export interface SampleDocument extends Document {
  // DB コレクション 型定義 (必ずスキーマと型を適合させる)
  _id: number;
  name: string;
  age: number;
}

const schema = new Schema(
  // スキーマ定義
  {
    _id: Number,
    name: { type: String },
    age: { type: Number }
  },
  // コレクション名を指定 (しないと mongoose が勝手に複数形に変えてしまう)
  { collection: collectionName }
);

/** サンプル モデル */
export const sampleModel = (con: Connection): Model<SampleDocument> => con.model(collectionName, schema);

処理クラス作成

モデルを利用して実処理を行う部分を作成する

server/accessor/db/accessors/sample.accessor.ts
import { DbAccessor } from '../db.accessor';
import { sampleModel, SampleDocument } from '../models/sample.model';

/** サンプル アクセサ */
export class SampleAccessor extends DbAccessor {

  /** 参照 */
  public async select(request: SampleDocument): Promise<SampleDocument[]> {

    const connection = await this.createConnection();
    const model = sampleModel(connection);

    // WHERE 句
    const whereCluse: SampleDocument = {} as SampleDocument;
    if (request.id) { whereCluse._id = request.id; }
    if (request.name) { whereCluse.name = request.name; }
    if (request.age) { whereCluse.age = request.age; }

    // ドキュメント取得
    return await model.find(whereCluse);
  }

  /** 挿入 */
  public async insert(request: SampleDocument): Promise<any> {

    const connection = await this.createConnection();
    const model = sampleModel(connection);

    // _id で降順に並び替え、最大値を取得
    const lastDocument = await model.findOne().select('_id').sort({ '_id': -1 });
    request._id = lastDocument ? lastDocument._id + 1 : 1;

    // 新 id でドキュメント作成
    return await model.create(request);
  }

  /** 更新 */
  public async update(id: number, request: SampleDocument): Promise<any> {

    const connection = await this.createConnection();
    const model = sampleModel(connection);

    // SET 句
    const setCluse: SampleDocument = {} as SampleDocument;
    if (request.name) { setCluse.name = request.name; }
    if (request.age) { setCluse.age = request.age; }

    return await model.findOneAndUpdate({_id: id}, setCluse);
  }

  /** 物理削除 */
  public async delete(id: number): Promise<any> {

    const connection = await this.createConnection();
    const model = sampleModel(connection);

    return await model.findByIdAndDelete(id);
  }
}

コントローラを修正

server/controllers/sample.controller.ts
import { SampleAccessor } from '../accessor/db/accessors/sample.accessor';
import { SampleDocument } from '../accessor/db/models/sample.model';
import { Sample } from '../../common/entities/sample/sample.entity';
import { ISamplePathParams, ISampleRequest, ISampleResponse } from '../../common/apis/sample/sample.api';

/** サンプル コントローラ */
export class SampleController {

  public async getUsers(request: ISampleRequest, params?: ISamplePathParams): Promise<ISampleResponse> {
    // ドキュメント検索 実行
    const dbRequest = { id: params.id, name: request.name, age: request.age } as SampleDocument;
    const dbResponse = await new SampleAccessor().select(dbRequest);

    // レスポンス生成
    const users: Sample[] = [];
    for (const element of dbResponse) {
      users.push({ id: element.id, name: element.name, age: element.age });
    }
    const response: ISampleResponse = { users: users };

    return response;
  }

  public async createUser(request: ISampleRequest): Promise<ISampleResponse> {
    // ドキュメント挿入 実行
    const dbRequest = { name: request.name, age: request.age } as SampleDocument;
    const dbResponse = await new SampleAccessor().insert(dbRequest); // 挿入されたドキュメントを返却

    // レスポンス生成
    const response: ISampleResponse = { users: [] };

    return response;
  }

  public async updateUser(request: ISampleRequest, params: ISamplePathParams): Promise<ISampleResponse> {
    // ドキュメント更新 実行
    const dbRequest = { name: request.name, age: request.age } as SampleDocument;
    const dbResponse = await new SampleAccessor().update(params.id, dbRequest); // 更新前のドキュメントを返却

    // レスポンス生成
    const response: ISampleResponse = { users: [] };

    return response;
  }

  public async deleteUser(request: ISampleRequest, params: ISamplePathParams): Promise<ISampleResponse> {
    // ドキュメント削除 実行
    const dbResponse = await new SampleAccessor().delete(params.id); // 削除されたドキュメントを返却

    // レスポンス生成
    const response: ISampleResponse = { users: [] };

    return response;
  }

}

確認

  • ブラウザで http://localhost:3000 にアクセスし、画面位表示されたボタンをクリック
  • 画面の動作結果が以下のとおりになっていればOK.

初期表示画面

ブラウザ初期表示状態

スクリーンショット 2019-02-11 0.12.23.png

検索(全検索)

条件を指定せずに検索ボタンを押すと、DB の Sample ドキュメントの全データを表示する。

スクリーンショット 2019-02-11 0.14.18.png

検索(条件検索)

条件を適用に指定して検索ボタンを押すと、DB の Sample ドキュメントを AND 検索する。
(画像では年齢で検索している)

スクリーンショット 2019-02-11 0.15.31.png

存在しない条件を指定すると、結果表示は空になる。

新規作成

作成に成功すると、成功したデータが表示される。(ID は自動発行するロジックに今回している)

スクリーンショット 2019-02-11 0.17.30.png

更新

作成したデータを一部更新してみる。指定したところだけが更新される。
(今回は、名前を「新しいデータ」を「更新したデータ」にしてみる)

スクリーンショット 2019-02-11 0.19.44.png

削除

作成したデータを 1 件削除してみる(今回は、論理削除でなく物理削除を実装)

スクリーンショット 2019-02-11 0.14.18.png

削除したデータが一覧から消えている。

以上で、MEAN スタックの Web アプリケーションが完成した。

あとは、node-config や forever 、log4js などのモジュールを入れて補強してください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む