<!DOCTYPE html>
<html ng-app="myApp">
<head>
<link data-require="toastr@*" data-semver="1.3.0" rel="stylesheet" href="//www.johnpapa.net/scripts/toastr.min.css" />
<link data-require="bootstrap@*" data-semver="3.3.2" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
<script data-require="jquery@*" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script data-require="bootstrap@*" data-sever="3.3.2" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script data-require="toastr@*" data-semver="1.3.0" src="//www.johnpapa.net/scripts/toastr.min.js"></script>
<script src="https://code.angularjs.org/1.3.15/angular.js" data-semver="1.3.15" data-require="angular.js@1.3.15"></script>
<script src="app.js"></script>
<script src="users-service.js"></script>
<script src="db-config-service.js"></script>
<script src="notification-service.js"></script>
</head>
<body>
<div class="container" ng-controller="AppCtrl">
<div class="alert alert-danger" ng-show="msg">{{msg}}</div>
<div class="alert alert-info loading" ng-show="users.length==0">Loading...</div>
<div class="panel panel-info">
<div class="panel-heading">
<strong>System Users</strong>
<span class="badge pull-right">Total Users : {{users.length}}</span>
</div>
<div class="panel-body">
<div class="row col-sm-12">
<div class="pull-left col-sm-6">Ordered by : <span class="badge">{{sort | uppercase}}{{sort? (reverse?' - Descending':' - Ascending'):'None'}}</span>
</div>
<div class="pull-right">
<span>Filtered by : </span>
<span ng-show="search.firstName">First Name =<span class="badge">{{search.firstName}}</span>
</span>
<span ng-show="search.lastName">Last Name =<span class="badge">{{search.lastName}}</span>
</span>
<span ng-show="search.email">Email =<span class="badge">{{search.email}}</span>
</span>
</div>
</div>
<table class="table table-striped table-bordered" ng-hide="users.length==0">
<thead>
<tr>
<th>
<input type="text" class="form-control" ng-model="search.firstName" placeholder="Filter by First Name" />
</th>
<th>
<input type="text" class="form-control" ng-model="search.lastName" placeholder="Filter by Last Name" />
</th>
<th>
<input type="text" class="form-control" ng-model="search.email" placeholder="Filter by Email" />
</th>
<th></th>
</tr>
<tr>
<th ng-click="setSort('firstName')">First Name<span class="pull-right arrow-up" ng-show="sort==='firstName' && reverse"></span>
<span class="pull-right arrow-down" ng-show="sort==='firstName' && !reverse"></span>
</th>
<th ng-click="setSort('lastName')">Last Name<span class="pull-right arrow-up" ng-show="sort === 'lastName' && reverse"></span>
<span class="pull-right arrow-down" ng-show="sort === 'lastName' && !reverse"></span>
</th>
<th ng-click="setSort('email')">Email<span class="pull-right arrow-up" ng-show="sort==='email' && reverse"></span>
<span class="pull-right arrow-down" ng-show="sort==='email' && !reverse"></span>
</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="user in users | filter:search | orderBy:sort:reverse | startFrom:currentPage*selectedPageSize | limitTo:selectedPageSize track by $index">
<td ng-click="editUser(user)">
<span ng-hide="user.editMode">{{user.firstName}}</span>
<input type="text" name="firstName" ng-show="user.editMode" class="form-control" ng-model="user.firstName" placeholder="First Name" required="" />
</td>
<td ng-click="editUser(user)">
<span ng-hide="user.editMode">{{user.lastName}}</span>
<input type="text" ng-show="user.editMode" name="lastName" class="form-control" ng-model="user.lastName" placeholder="Last Name" required="" />
</td>
<td ng-click="editUser(user)">
<span ng-hide="user.editMode">{{user.email}}</span>
<input type="text" ng-show="user.editMode" name="email" class="form-control" ng-model="user.email" placeholder="Email" required="" />
</td>
<td>
<a href="" ng-hide="user.editMode" ng-click="editUser(user)">Edit</a>
<a href="" ng-hide="user.editMode" ng-click="delete(user,$index)">Delete</a>
<a href="" ng-show="user.editMode" ng-click="saveUser(user,$index)">Update</a>
<a href="" ng-show="user.editMode" ng-click="cancel(user)">Cancel</a>
</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-sm-2">
<span class="col-sm-5">Pagesize:</span>
<span class="col-sm-7">
<select class="form-control" ng-options="pageSize for pageSize in pageSizes" ng-model="selectedPageSize"></select>
</span>
</div>
<div class="col-sm-6">
<button class="btn btn-small btn-info" ng-disabled="currentPage <1" ng-click="currentPage=currentPage-1">Prev Page</button>
<!--span class="col-sm-3">Goto Page:</span>
<span class="col-sm-2">
<select class="form-control" ng-options="page for page in pages" ng-model="currentPage"></select>
</span-->
<button class="btn btn-small btn-info" ng-disabled="currentPage >= users.length/selectedPageSize - 1" ng-click="currentPage=currentPage+1">Next Page</button>
</div>
<div class="pull-right col-sm-4">
<button class="btn btn-warning" ng-click="refreshUsers()">Refresh</button>
<button class="btn btn-success" ng-click="bulkUpdateUsers()">Bulk Update</button>
<button class="btn btn-danger" ng-click="bulkDeleteUsers()">Bulk Delete</button>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
// Code goes here
(function() {
//create application module
var app = angular.module("myApp", []);
//create main app controller
app.controller("AppCtrl", function($scope, usersSvc, notificationService) {
//maintain a user list (initialy blank)
var defaultSort = 'firstName';
$scope.users = [];
$scope.msg = "";
$scope.sort = defaultSort;
$scope.reverse = false;
$scope.selectedPageSize = 3;
$scope.pageSizes = [1, 2, 3];
$scope.currentPage = 1;
$scope.pages = [1, 2, 3, 4];
$scope.setSort = function(sort) {
if ($scope.sort === sort) {
$scope.reverse = !$scope.reverse;
}
if ($scope.sort !== undefined) {
$scope.sort = sort;
}
}
//define user CRUD operations
//save user (create & update)
$scope.saveUser = function(user, index) {
if (user.editMode) {
user.editMode = false;
$scope.sort = defaultSort;
usersSvc.updateUser(user, index)
.then(function() {
notificationService.success("User updated successfully.");
}, function(response) {
$scope.msg = response;
});
} else {
usersSvc.createUser(user)
.then(function() {
notificationService.success("User created successfully.");
}, function(response) {
$scope.msg = response;
});
}
}
//bulk update users
$scope.bulkUpdateUsers = function() {
for (var i = 0; i < $scope.users.length; i++) {
var user = $scope.users[i];
if (user.editMode) {
$scope.saveUser(user, i);
}
}
}
//var lastEditedUser={};
//edit user details
$scope.editUser = function(user) {
//angular.extend(lastEditedUser,user);
user.editMode = true;
$scope.sort = undefined;
}
//cancel
$scope.cancel = function(user) {
getAllUsers();
user.editMode = false;
//angular.extend(user,lastEditedUser);
}
//delete user
$scope.deleteUser = function(user, index) {
$scope.users = [];
usersSvc.deleteUser(user, index)
.then(function(response) {
user.editMode = false;
refreshUsers();
notificationService.success("User deleted successfully.");
}, function(response) {
$scope.msg = response;
});
}
$scope.bulkDeleteUsers = function() {
for (var i = 0; i < $scope.users.length; i++) {
var user = $scope.users[i];
if (user.editMode) {
$scope.deleteUser(user, i);
}
}
}
//get all users
function getAllUsers() {
$scope.sort = defaultSort;
usersSvc.retrieveAllUsers()
.then(function(response) {
$scope.users = angular.copy(response.data);
}, function(response) {
$scope.msg = response;
});
}
function refreshUsers() {
$scope.users = [];
getAllUsers();
}
$scope.refreshUsers = refreshUsers;
//fetch all users
getAllUsers();
});
//start from filter
app.filter('startFrom', function() {
return function(input, start) {
start = +start; //parse to int
return input.slice(start);
}
});
}());
/* Styles go here */
.container {
margin-top: 50px;
}
input.ng-invalid.ng-dirty {
background-color: rgb(255, 200, 200);
border-color: red;
}
.loading {
position: absolute;
left: 45%;
top: 45%;
}
.arrow-up {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid black;
margin-top: 10px;
}
.arrow-down {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid black;
margin-top: 10px;
}
Angular Table
Sorting
Filtering
Inline-editing
Bulk-update
Online Mongolab Integration
(function(){
//load main module
var app=angular.module("myApp");
app.value("notificationService",window.toastr);
}());
(function() {
//load main module
var app = angular.module("myApp");
var debugMode = true;
var offlineUsers = [];
for (var i = 0; i < 5; i++) {
offlineUsers.push({
firstName: "debug" + i + "_firstName",
lastName: "debug" + i + "_lastName",
email: "debug" + i + "_email"
});
}
app.factory("usersSvc", function($q, $http, dbConfigService) {
//-----------------offline user CRUD operations-----------------------
//createUser
function createUserOffline(user) {
var dfd = new $q.defer();
offlineUsers = offlineUsers || [];
offlineUsers.push(user);
dfd.resolve("");
return dfd.promise;
}
//retrieveAllUsers
function retrieveAllUsersOffline() {
var dfd = new $q.defer();
offlineUsers = offlineUsers || [];
dfd.resolve({
data: offlineUsers
});
return dfd.promise;
}
//updateUser
function updateUserOffline(user, index) {
var dfd = new $q.defer();
if (offlineUsers) {
offlineUsers[index] = angular.copy(user);
}
dfd.resolve("");
return dfd.promise;
}
//deleteUser
function deleteUserOffline(user, index) {
var dfd = new $q.defer();
if (offlineUsers) {
offlineUsers.splice(index, 1);
}
dfd.resolve("");
return dfd.promise;
}
//----------------------User CRUD operations------------------------------------------
//createUser
function createUser(user) {
return $http.post(dbConfigService.url, user, {
params: {
apiKey: dbConfigService.key
}
});
}
//retrieveAllUsers
function retrieveAllUsers() {
return $http.get(dbConfigService.url, {
params: {
apiKey: dbConfigService.key
}
});
}
//updateUser
function updateUser(user, index) {
return $http.put(dbConfigService.url + "/" + user._id.$oid, user, {
params: {
apiKey: dbConfigService.key
}
});
}
//deleteUser
function deleteUser(user, index) {
return $http.delete(dbConfigService.url + "/" + user._id.$oid, {
params: {
apiKey: dbConfigService.key
}
});
}
return {
createUser: debugMode ? createUserOffline : createUser,
retrieveAllUsers: debugMode ? retrieveAllUsersOffline : retrieveAllUsers,
updateUser: debugMode ? updateUserOffline : updateUser,
deleteUser: debugMode ? deleteUserOffline : deleteUser
};
});
}());
(function() {
//get main app module
var app = angular.module("myApp");
app.value("dbConfigService", {
url: "https://api.mongolab.com/api/1/databases/users/collections/users",
key: "Wdc5sXvl48AUtNVVobU4rSbxrrUNOQIe"
});
}());