Skip to content

Instantly share code, notes, and snippets.

@edm00se
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edm00se/369294c9a2fe54e8c1ec to your computer and use it in GitHub Desktop.
Save edm00se/369294c9a2fe54e8c1ec to your computer and use it in GitHub Desktop.
Supporting code to the blog post of Building a Front-End: An App with AngularJS and HTTPServlet. src: http://edm00se.io/xpages-servlets/-building-a-front-end-pt2-an-app-with-angular/
// a self-invoking, anonymouse function to keep application code variables scoped anonymously
(function(){
//defines the AngularJS app as a module
angular.module('houseApp', ['ui.router']) //'ngAnimate'
//ui-router config
.config(
function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/houses');
$stateProvider
.state('houses', {
url: '/houses',
templateUrl: 'partials/houseList.html',
controller: 'HouseListCtrl'
})
.state('houses.item', {
url: '/:item',
templateUrl: 'partials/house.html',
controller: 'OneHouseCtrl'
});
})
// ... services/factories, controllers, filters, directives
})();
//...config,factories...
/*
* Controllers
*/
//navigation controller
.controller('NavCtrl', function($scope, $location){
$scope.isActive = function(route) {
return route === $location.path();
}
})
//provies the controller to the app, which handles the interaction of data (model) with the view (a la MVC)
.controller('HouseListCtrl', function($scope, $state, $http, $filter, houseCollectionFactory) {
//defines filter/search/etc. vars
$scope.pageQty = 5; //detectPhone() ? 10 : 30;
$scope.curPage = 0;
//calculates the number of results
$scope.numberOfPages = function() {
return Math.ceil($scope.housesOfWesteros.length / $scope.pageQty) || 0;
}
//defines a boolean var
$scope.showSearch = false;
$scope.housesOfWesteros = [];
//the factory is returning the promise of the $http, so handle success/error here
houseCollectionFactory
.success( function(data, status, headers, config) {
$scope.housesOfWesteros = data;
//$scope.predicate = "JobNum";
//$scope.reverse = false;
}).error( function(data, status, headers, config) {
$scope.housesOfWesteros = null;
console.log("data: " + data);
console.log("status: " + status);
console.log("headers: " + headers);
console.log("config: " + JSON.parse(config));
})
.then( function(){
//angular.element('div.screenMask').css('visibility','hidden');
});
$scope.removeHouse = function(unid){
$http( {
method : 'DELETE',
url : 'houses/'+unid
})
.success( function(data, status, headers, config){
console.log("successfully deleted house with id: "+unid);
})
.error( function(data, status, headers, config){
//might as well say something
console.log("poop");
})
.then( function(){
$state.go('houses',{reload: true});
});
};
})
.controller('OneHouseCtrl', function($scope, $state, $stateParams, $http, houseFactory){
// check for empty ID
var tmpItm = $stateParams.item;
console.log("unid: "+tmpItm);
var re = /^[0-9A-Za-z]{32}$/;
//var re = /\d/;
if( tmpItm == null || tmpItm == undefined || (!tmpItm || !tmpItm.trim()) || !re.test(tmpItm) ){
$state.go('houses');
}
$scope.editForm = false;
$scope.canEditForm = false;
$scope.myHouse = {};
var fieldNames = [];
houseFactory($stateParams.item)
.success(function(data, status, headers, config) {
$scope.myHouse = data;
$scope.canEditForm = true;
angular.forEach($scope.myHouse,function(value,key){
if( key!="unid" ){
fieldNames.push(key);
}
});
})
.error(function(data, status, headers, config) {
console.log("status: "+status);
console.log("data: "+data);
console.log("headers: "+headers);
console.log("config: "+JSON.parse(config));
});
$scope.setFormEditable = function() {
if( $scope.canEditForm == true ){
$scope.editForm = true;
}
}
$scope.clearCancelForm = function() {
$state.go('houses');
}
$scope.saveHouseForm = function(){
var tmpOb = { "unid": $scope.myHouse.unid };
//console.log("checking field names: "+fieldNames.toString());
angular.forEach(fieldNames, function(fldNm){
if( $scope.houseForm[fldNm].$dirty === true ){
var tmpVal = $scope.myHouse[fldNm];
//console.log("updated field: "+fldNm+" with value: "+tmpVal);
tmpOb[fldNm] = tmpVal;
}
});
$http( {
method : 'PUT',
url : 'houses/'+$scope.myHouse.unid,
data: JSON.stringify(tmpOb)
})
.success( function(data, status, headers, config){
console.log("successfully updated house with unid: "+$scope.myHouse.unid);
})
.error( function(data, status, headers, config){
//might as well say something
console.log("poop");
})
.then( function(){
$state.go('houses',{reload: true});
});
//console.log("Simulated PUT complete with object to send: "+JSON.stringify(tmpOb));
}
})
//...filters,directives...
//...config,factories,controllers,filters
/*
* Directives
*/
//This directive allows us to pass a function in on an enter key to do what we want.
.directive('ngEnter', function () {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if(event.which === 13) {
scope.$apply(function (){
scope.$eval(attrs.ngEnter);
});
event.preventDefault();
}
});
};
})
/**
* A generic confirmation for risky actions.
* Usage: Add attributes: ng-really-message="Are you sure"? ng-really-click="takeAction()" function
*/
.directive('ngReallyClick', [function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('click', function() {
var message = attrs.ngReallyMessage;
if (message && confirm(message)) {
scope.$apply(attrs.ngReallyClick);
}
});
}
}
}]);
//...nothing, just close the parenthesis to make the JS object complete then invoke with another set of paren
//...config...
/*
* Factories
*/
//defines the $HTTP factory, one of the 3 service types
.factory('houseCollectionFactory', [ '$http', function($http) {
return $http( {
method : 'GET',
url : 'houses'
});
} ])
.factory('houseFactory', [ '$http', function($http){
return function(id){
return $http( {
method : 'GET',
url : 'houses/'+id
});
}
}])
//...controllers,filters,directives...
//...config,factories,controllers...
/*
* Filters
*/
// we already use the limitTo filter built-in to AngularJS,
// this is a custom filter for startFrom
.filter('startFrom', function() {
return function(input, start) {
start = +start; //parse to int
return input.slice(start);
}
})
//...directives...
<!-- ...head contents... -->
<!-- defining where to inject our app definition, using the body tag -->
<body ng-app="houseApp">
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<!-- ...navbar contents... -->
</div>
<!-- the magic! -->
<div ui-view></div>
<!-- CDN driven resources for Bootstrap and AngularJS JS resource files -->
<script type="text/javascript" src="js/houseApp.js"></script>
</body>
<!-- ... -->
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">House Details</h3>
</div>
<div class="panel-body">
<form name="houseForm">
<div class="form-group">
<label
for="houseName">
Name</label>
<input
type="text"
class="form-control"
id="houseName"
name="name"
ng-model="myHouse.name"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="houseDescription">
Description</label>
<textarea
class="form-control"
id="houseDescription"
name="description"
ng-model="myHouse.description"
rows="3"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="coatOfArms">
Coat of Arms</label>
<input
type="text"
class="form-control"
id="coatOfArms"
name="coatOfArms"
ng-model="myHouse.coatOfArms"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="houseWords">
Words</label>
<input
type="text"
class="form-control"
id="houseWords"
name="words"
ng-model="myHouse.words"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="houseSeat">
Seat</label>
<input
type="text"
class="form-control"
id="houseSeat"
name="seat"
ng-model="myHouse.seat"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="houseCurrentLord">
Current Lord</label>
<input
type="text"
class="form-control"
id="houseCurrentLord"
name="currentLord"
ng-model="myHouse.currentLord"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="houseRegion">
Region</label>
<input
type="text"
class="form-control"
id="houseRegion"
name="region"
ng-model="myHouse.region"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="houseTitle">
Title</label>
<input
type="text"
class="form-control"
id="houseTitle"
name="title"
ng-model="myHouse.title"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="houseHeir">
Heir</label>
<input
type="text"
class="form-control"
id="houseHeir"
name="heir"
ng-model="myHouse.heir"
ng-disabled="!editForm" />
</div>
<div class="form-group">
<label
for="houseOverlord">
Overlord</label>
<input
type="text"
class="form-control"
id="houseOverlord"
name="overlord"
ng-model="myHouse.overlord"
ng-disabled="!editForm" />
</div>
<div class="btn-list pull-right">
<button
class="btn-default btn"
type="button" id="buttonCancelGotHouse"
ng-really-message="Are you sure?"
ng-really-click="clearCancelForm()">
<i class="fa fa-lg fa-pencil"></i> Cancel</button>
<button
class="btn-success btn"
type="button" id="buttonSaveGotHouse"
ng-show="editForm"
ng-click="saveHouseForm()">
<i class="fa fa-lg fa-save"></i> Save</button>
<button
class="btn-primary btn"
type="button" id="buttonEditGotHouse"
ng-disabled="!canEditForm"
ng-show="!editForm"
ng-click="setFormEditable()">
<i class="fa fa-lg fa-pencil"></i> Edit</button>
</div>
</form>
</div>
<!-- <div class="panel-footer col-xs-12"></div> -->
</div>
<div id="uiContainer" class="container">
<div class="row">
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Houses of the Seven Kingdoms of Westeros</h3>
</div>
<ul class="list-group list-group-striped">
<li class="list-group-item"
ng-repeat="house in housesOfWesteros | startFrom : curPage*pageQty | limitTo:pageQty">
<a ng-href="#/houses/{{ house.unid }}" title="{{ house.unid }}">{{house.name}}</a>
<a href="#"
class="btn btn-danger pull-right"
ng-really-message="Are you sure you want to delete this house from Westeros?"
ng-really-click="removeHouse(house.unid)"><i class="fa fa-lg fa-trash-o"></i></a>
<br />{{house.words}}
</li>
</ul>
<div class="panel-footer col-xs-12">
<nav>
<ul class="pager">
<li class="previous" ng-class="{'disabled': curPage == 0}">
<a ng-click="curPage = curPage - 1" href=""><span aria-hidden="true">&larr;</span> Previous</a>
</li>
<span ng-bind="(curPage+1) + '/' + numberOfPages()"></span>
<li class="next" ng-class="{'disabled': curPage >= housesOfWesteros.length/pageQty-1}">
<a ng-click="curPage = curPage + 1" href="">Next <span aria-hidden="true">&rarr;</span></a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<!-- single house content -->
<div ui-view class="col-md-6 col-md-offset-2"></div>
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment