NodeとAngularを使用したシングルページTodoアプリの作成
注:編集#1:ng-initを削除する
序章
今日は、MEAN(Mongo、Express、Angular、Node)スタックを使用して非常に単純なTodoアプリケーションを作成します。 作成します:
- ToDoを作成して終了するシングルページアプリケーション
- Mongooseを使用してMongoDBにtodoを保存する
- Expressフレームワークの使用
- RESTfulノードAPIの作成
- フロントエンドとAPIへのアクセスにAngularを使用する
この記事はExpressJS4.0用に更新されました]。
アプリケーションはシンプルで、それ自体が初級から中級レベルですが、ここでの概念は、はるかに高度なアプリに適用できます。 私たちが焦点を当てるべき最大のことは、ノードをAPIとして使用し、Angularをフロントエンドとして使用することです。 それらを一緒に動作させることは少し混乱する可能性があるので、このチュートリアルはいくつかの混乱を軽減するのに役立つはずです。 それらのシートベルトを締めます。 これは長いものになる可能性があります。
基本設定
ファイル構造
ファイル構造を非常にシンプルに保ち、Nodeアプリケーションのほとんどのコードをserver.js
ファイルに配置します。 大規模なアプリケーションでは、これをさらに細かく分けて職務を分離する必要があります。 Mean.io は、ベストプラクティスとファイル構造を分離する方法を確認するための優れた定型文です。 先に進んで、より単純なファイル構造を作成し、ファイルを編集していきましょう。
- public <!-- holds all our files for our frontend angular application --> ----- core.js <!-- all angular code for our app --> ----- index.html <!-- main view --> - package.json <!-- npm configuration to install dependencies/modules --> - server.js <!-- Node configuration -->
モジュールのインストール
Nodeでは、package.json
ファイルにアプリの構成が保持されます。 ノードのパッケージマネージャー(npm)はこれを使用して、使用する依存関係またはモジュールをインストールします。 この例では、 Express (人気のあるノードフレームワーク)と Mongoose (MongoDBのオブジェクトモデリング)を使用します。
{ "name" : "node-todo", "version" : "0.0.0", "description" : "Simple todo application.", "main" : "server.js", "author" : "Scotch", "dependencies" : { "express" : "~4.7.2", "mongoose" : "~3.6.2", "morgan" : "~1.2.2", "body-parser": "~1.5.2", "method-override": "~2.1.2" } }
npm install
を実行すると、npmはこのファイルを調べて、ExpressとMongooseをインストールします。
ノード構成
package.json
ファイルで、メインファイルはserver.js
になると伝えました。 これはノードアプリのメインファイルであり、アプリケーション全体を構成します。
これは、次のファイルです。
- アプリケーションを構成する
- 私たちのデータベースに接続します
- マングースモデルを作成する
- RESTfulAPIのルートを定義する
- フロントエンドAngularアプリケーションのルートを定義する
- ブラウザで表示できるように、ポートでリッスンするようにアプリを設定します
今のところ、Express、MongoDBデータベース、およびポートでリッスンするようにアプリを構成します。
// server.js // set up ======================== var express = require('express'); var app = express(); // create our app w/ express var mongoose = require('mongoose'); // mongoose for mongodb var morgan = require('morgan'); // log requests to the console (express4) var bodyParser = require('body-parser'); // pull information from HTML POST (express4) var methodOverride = require('method-override'); // simulate DELETE and PUT (express4) // configuration ================= mongoose.connect('mongodb://user:[email protected]:port/database'); // connect to mongoDB database on modulus.io app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users app.use(morgan('dev')); // log every request to the console app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-urlencoded app.use(bodyParser.json()); // parse application/json app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json app.use(methodOverride()); // listen (start app with node server.js) ====================================== app.listen(8080); console.log("App listening on port 8080");
ほんの少しのコードで、NodeのおかげでHTTPサーバーができました。 Expressを使用してアプリも作成し、その多くのメリットを利用できるようになりました。 app.configure
セクションでは、エクスプレスモジュールを使用して、アプリケーションに機能を追加しています。
データベースの設定
Modulus.ioでホストされているリモートデータベースを使用します。 彼らは素晴らしいサービスを提供し、あなたが適切と思うように使用するためにあなたに前もって15ドルを与えます。 これは、データベースのテストと作成をその場で行うのに最適です。
Modulusは必要なデータベースURLを提供し、mongoose.connect
を使用してそれに接続できます。 それでおしまい。
アプリを起動してください!
package.json
とserver.js
が起動したので、サーバーを起動して何が起こっているかを確認できます。 コンソールに移動して、次のコマンドを使用するだけです。
node server.js
これで、サーバーがポート8080でリッスンします。 http://localhost:8080
では、何も出力するようにアプリケーションを構成していないため、ブラウザーにはまだ何も表示されません。 しかし、それは始まりです!
ファイルが変更されたときにサーバーを自動的に再起動します:デフォルトでは、サーバーの起動後、ノードはファイルの変更を監視しません。 つまり、ファイルを変更するたびにサーバーをシャットダウンして起動する必要があります。 これはnodemonで修正できます。 使用するには:nodemonをグローバルにインストールしますnpm install -g nodemon
。 今すぐnodemon server.js
でサーバーを起動します。 そこからスムーズな航海。
アプリケーションフロー
次に、すべての可動部品がどのように連携するかについて簡単に説明します。 このアプリケーションにはさまざまなアイデアやテクノロジーが含まれているため、それらすべてと簡単に混同されてしまいます。
Angularはそれ自体がフロントエンドにあります。 NodeAPIを介して必要なすべてのデータにアクセスします。 ノードはデータベースにアクセスし、RESTfulルーティングに基づいてJSON情報をAngularに返します。
このようにして、フロントエンドアプリケーションを実際のAPIから分離できます。 APIを拡張したい場合は、フロントエンドのAngularアプリケーションに影響を与えることなく、いつでもより多くのルートと関数をAPIに組み込むことができます。 このように、APIをヒットするだけでよいため、最終的にはさまざまなプラットフォームでさまざまなアプリを構築できます。
ノードAPIの作成
フロントエンドアプリケーションに到達する前に、RESTfulAPIを作成する必要があります。 これにより、すべてのtodos を取得し、 todo を作成し、completeしてtodoを削除するAPIを使用できるようになります。 このすべての情報をJSON形式で返します。
Todoモデル
Todoのモデルを定義する必要があります。 これは単純にしておきます。 構成セクションの後、リッスンセクションの前に、モデルを追加します。
// define model ================= var Todo = mongoose.model('Todo', { text : String });
それが私たちが望むすべてです。 ToDoのテキストだけです。 MongoDBは、作成するToDoごとに_id
を自動的に生成します。
RESTfulAPIルート
API呼び出しを処理するためのExpressルートを生成しましょう。
// server.js ... // routes ====================================================================== // api --------------------------------------------------------------------- // get all todos app.get('/api/todos', function(req, res) { // use mongoose to get all todos in the database Todo.find(function(err, todos) { // if there is an error retrieving, send the error. nothing after res.send(err) will execute if (err) res.send(err) res.json(todos); // return all todos in JSON format }); }); // create todo and send back all todos after creation app.post('/api/todos', function(req, res) { // create a todo, information comes from AJAX request from Angular Todo.create({ text : req.body.text, done : false }, function(err, todo) { if (err) res.send(err); // get and return all the todos after you create another Todo.find(function(err, todos) { if (err) res.send(err) res.json(todos); }); }); }); // delete a todo app.delete('/api/todos/:todo_id', function(req, res) { Todo.remove({ _id : req.params.todo_id }, function(err, todo) { if (err) res.send(err); // get and return all the todos after you create another Todo.find(function(err, todos) { if (err) res.send(err) res.json(todos); }); }); }); ...
これらのルートに基づいて、フロントエンドアプリケーションがAPIからデータを要求する方法を説明するテーブルを作成しました。
HTTP動詞 | URL | 説明 |
---|---|---|
得る | /api/todos
|
すべてのToDoを取得する |
役職 | /api/todos
|
単一のToDoを作成する |
消去 | /api/todos/:todo_id
|
1つのToDoを削除する |
各APIルート内で、Mongooseアクションを使用してデータベースとの対話を支援します。 以前にvar Todo = mongoose.model
を使用してモデルを作成しましたが、これを使用して find 、 create 、およびremoveを実行できます。 できることは他にもたくさんあります。詳細については、公式のドキュメントをご覧になることをお勧めします。
APIが完成しました! 喜んで! アプリケーションを起動すると、localhost:8080/api/todos
でアプリケーションを操作して、すべてのタスクを取得できます。 何も追加していないので、現在は何もありません。
Angularを使用したフロントエンドアプリケーション
ノードアプリケーションの作成、データベースの構成、 APIルートの生成、サーバーの起動を行いました。 すでに多くのことが行われていますが、まだ少し長くなります!
これまでに行ってきた作業は、アプリケーションとして自立することができます。 これは、アプリケーションとユーザーがコンテンツに接続できるようにするために使用するAPIにすることができます。
作成したばかりの新しいAPIを最初に使用したいと考えています。 これは、先月私が学んだ私のお気に入りの用語の1つです。私たちはdogfoodingになります。 新しいAPIを使用する最初のクライアントであるため、これを扱うことができます。 これを単純にするため、フロントエンドを定義するのはindex.html
とcore.js
だけです。
フロントエンドルートの定義
APIルートはすでに定義されています。 アプリケーションのAPIには/api/todos
からアクセスできますが、フロントエンドについてはどうでしょうか。 ホームページにindex.htmlファイルを表示するにはどうすればよいですか?
フロントエンドアプリケーションのserver.js
ファイルに1つのルートを追加します。 Angularはシングルページアプリケーションを作成し、ルーティングを処理するため、これが必要なすべてです。
APIルートの後、app.listen
の前に、次のルートを追加します。
// server.js ... // application ------------------------------------------------------------- app.get('*', function(req, res) { res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end) }); ...
これにより、localhost:8080
を押すと、単一のindex.htmlファイルが読み込まれます。
Angularcore.jsの設定
最初にAngularのセットアップを見てみましょう。 モジュールを作成、コントローラーを作成、タスクを処理する関数を定義する必要があります。 次に、ビューに適用できます。
// public/core.js var scotchTodo = angular.module('scotchTodo', []); function mainController($scope, $http) { $scope.formData = {}; // when landing on the page, get all todos and show them $http.get('/api/todos') .success(function(data) { $scope.todos = data; console.log(data); }) .error(function(data) { console.log('Error: ' + data); }); // when submitting the add form, send the text to the node API $scope.createTodo = function() { $http.post('/api/todos', $scope.formData) .success(function(data) { $scope.formData = {}; // clear the form so our user is ready to enter another $scope.todos = data; console.log(data); }) .error(function(data) { console.log('Error: ' + data); }); }; // delete a todo after checking it $scope.deleteTodo = function(id) { $http.delete('/api/todos/' + id) .success(function(data) { $scope.todos = data; console.log(data); }) .error(function(data) { console.log('Error: ' + data); }); }; }
Angularモジュール(scotchApp
)とコントローラー(mainController
)を作成します。
また、すべてのtodoを取得、 todoを作成、todoを削除する関数も作成します。 これらはすべて、作成したAPIにヒットします。 ページの読み込み時に、GET /api/todos
を実行し、APIから受け取ったJSONを$scope.todos
にバインドします。 次に、これらをビューでループして、ToDoを作成します。
作成と削除についても同様のパターンに従います。 アクションを実行し、ToDoリストを作り直します。
フロントエンドビューindex.html
ここでは、それを単純に保ちます。 これは、Angularと対話するために必要なHTMLです。 私達はします:
- Angularモジュールとコントローラーを割り当てる
- すべてのタスクを取得してページを初期化します
- ToDoをループします
- ToDoを作成するためのフォームがあります
- チェックされたらtodoを削除します
<!-- index.html --> <!doctype html> <!-- ASSIGN OUR ANGULAR MODULE --> <html ng-app="scotchTodo"> <head> <!-- META --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Optimize mobile viewport --> <title>Node/Angular Todo App</title> <!-- SCROLLS --> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"><!-- load bootstrap --> <style> html { overflow-y:scroll; } body { padding-top:50px; } #todo-list { margin-bottom:30px; } </style> <!-- SPELLS --> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script><!-- load jquery --> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script><!-- load angular --> <script src="core.js"></script> </head> <!-- SET THE CONTROLLER AND GET ALL TODOS --> <body ng-controller="mainController"> <div class="container"> <!-- HEADER AND TODO COUNT --> <div class="jumbotron text-center"> <h1>I'm a Todo-aholic <span class="label label-info">{{ todos.length }}</span></h1> </div> <!-- TODO LIST --> <div id="todo-list" class="row"> <div class="col-sm-4 col-sm-offset-4"> <!-- LOOP OVER THE TODOS IN $scope.todos --> <div class="checkbox" ng-repeat="todo in todos"> <label> <input type="checkbox" ng-click="deleteTodo(todo._id)"> {{ todo.text }} </label> </div> </div> </div> <!-- FORM TO CREATE TODOS --> <div id="todo-form" class="row"> <div class="col-sm-8 col-sm-offset-2 text-center"> <form> <div class="form-group"> <!-- BIND THIS VALUE TO formData.text IN ANGULAR --> <input type="text" class="form-control input-lg text-center" placeholder="I want to buy a puppy that will love me forever" ng-model="formData.text"> </div> <!-- createToDo() WILL CREATE NEW TODOS --> <button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button> </form> </div> </div> </div> </body> </html>
私たちが持っているものを見てください。
結論
これで、(作成した)APIを介してすべてのToDoを表示、作成、および削除する、完全に機能するアプリケーションができました。 それはかなりの日でした。 私たちはたくさんのことをしました。 私たちが達成したことの概要:
- Expressを使用したRESTfulノードAPI
- マングースを使用したMongoDBインタラクション
- Angular AJAX$http呼び出し
- 更新なしのシングルページアプリケーション
- ドッグフーディング(申し訳ありませんが、私はその言葉が本当に好きです)
アプリケーションをテストする
先に進み、 GitHub にコードをダウンロードして、微調整またはテストします。 すべてを稼働させるには:
- Nodeとnpmがインストールされていることを確認してください
- リポジトリのクローンを作成します:
git clone [email protected]:scotch-io/node-todo
- アプリケーションをインストールします:
npm install
- サーバーを起動します:
node server.js
http://localhost:8080
でブラウザに表示します
これが、多くの可動部品を連携させる方法について洞察に満ちたものであったことを願っています。 将来的には、server.js
ファイルを分離することを検討します。これは、少しおかしくなったためです。
参考資料より多くのMEANスタックアプリケーションに興味がある場合は、独自のMEANスタック基盤の構築を開始するためのガイドを作成しました。
この記事は、Node and AngularTo-DoAppシリーズの一部です。
- NodeとAngularを使用して単一ページのToDoアプリを作成する
- ノードアプリケーションの構成と構造
- Angularモジュール:コントローラーとサービス