Comprehensive MEAN(Mongo, Express, Angular, and Nodejs) with Docker III
Angularjs is a very popular js framework backed by Google. So my front end site will base on Angularjs and adding other tools like bootstrap and ui-router.
The all four article is
- Environment setting - develop MEAN with docker.
- Nodejs and Express.
- *Angularjs.
- Continuous Development.
App architecture
Project Architecture
/app
|---/pages
|---index.html
|---index.js
|---/about
| |---memoAbout.html
|---/memo
|---memoController.js
|---memoPage.html
server.js
Dockerfile
docker-compose.yml
package.json
bower.json
Gulpfile.js
Bower.json
Bower is another popular package management tool for front end development. It works like npm.
{
"name": "memoApp",
"version": "0.0.0",
"author": "Wei Ting Cheng <waitinduck@gmail.com>",
"dependencies": {
"angular": "^1.5.4",
"angular-ui-router": "0.2.18",
"bootstrap": "3.0.0"
}
}
index.html
<!doctype html>
<!-- create your angularjs app -->
<html ng-app="memoApp">
<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>
<!-- this is the place gulp will insert package like angularjs or bootstrap. I will explain more on this in the latter post-->
<!-- inject:css -->
<!-- endinject -->
<!-- bowercss:css-->
<!-- endinject -->
</head>
<!-- SET THE CONTROLLER AND GET ALL TODOS -->
<body>
<nav class="navbar navbar-inverse" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" ui-sref="memo">MemoApp</a>
</div>
<ul class="nav navbar-nav">
<li><a ui-sref="memo">Memo</a></li>
<li><a ui-sref="about">About</a></li>
</ul>
</nav>
<!-- will show the page in ui-view div-->
<div class="container">
<div ui-view></div>
</div>
<!-- bowerjs:js-->
<!-- endinject -->
<!-- inject:js -->
<!-- endinject -->
</body>
</html>
One thing noted here. angularjs compile html file first. Which mean you need to specify ng-app, ng-controller in html, otherwise angularjs wont recognize it. I am using ui-router here so I could save sometime on write ng-controller.
index.js
angular.module('memoApp', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state('memo', {
url: '/',
templateUrl: 'pages/memo/memoPage.html',
controller: 'memoController'
})
// ABOUT PAGE
.state('about', {
url: '/about',
templateUrl: 'pages/about/memoAbout.html'
});
}]);
I use ui-router here. You can learn more about this tool in here. It will insert controller and template for you and allow you have nested route.
memoPage.html
<!-- HEADER AND TODO COUNT -->
<div class="jumbotron text-center">
<h1>I'm a Memo <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>
memoPageController.js
angular.module('memoApp')
.controller('memoController', ['$scope', '$http',
function($scope, $http) {
$scope.formData = {};
// when landing on the page, get all todos and show them
$http.get('/todos')
.success(function(data) {
$scope.todos = 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('/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('/todos/' + id)
.success(function(data) {
$scope.todos = data;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
}]);
Further Reading
You can find this code in my github repo MEAN pracitce.
- angularjs
- ui-router
- ui-bootstrap - a very good bootstrap plugin backed by angular team.