So You Want to Build a SPA
by John Tucker
HTML
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-route.min.js"></script>
<script src="//cdn.firebase.com/js/client/2.0.6/firebase.js"></script>
<!-- index.html -->
<!-- normally files are stored in separate files; need to src js
<script src="controllers/my_controllers.js"></script>
<script src="app.js"></script>
<script src="routes/routes.js"></script>
-->
<div ng-app="myApp">
<div ng-view></div>
<!-- /views/home.html (obmit work-around script tag)-->
<script type="text/ng-template" id="views/home.html">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Home</h3>
</div>
<ul class="list-group">
<li ng-if="! authenticated" ng-click="navigate('/login');" class="list-group-item">Login</li>
<li ng-if="authenticated" ng-click="logout();" class="list-group-item">Logout</li>
<li ng-click="navigate('/wineries');" class="list-group-item">Wineries</li>
<li ng-click="navigate('/wines');" class="list-group-item">Wines</li>
</ul>
</div>
</script>
<!-- EOF -->
<!-- /views/login.html (obmit work-around script tag)-->
<script type="text/ng-template" id="views/login.html">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><button ng-click="navigate('/');" class="btn btn-default"><span class="glyphicon glyphicon-chevron-left"></span> Back</button> Login</h3>
</div>
<div class="panel-body">
<form name="login_form" role="form" novalidate>
<div ng-class="{'form-group': true, 'has-feedback': true, 'has-error': login_form.email.$invalid}">
<label class="control-label"...
CSS
</style>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<style>
JavaScript
// controllers/my_controllers.js
var controllers = angular.module('myControllers', []);
controllers.controller('HomeCntrl', ['$scope', '$location', '$window', function($scope, $location, $window) {
var myDataRef;
$scope.navigate = function(path) {
$location.path(path);
};
$scope.authenticated = false;
myDataRef = new $window.Firebase('https://wineapp.firebaseio.com');
$scope.logout = function() {
$scope.authenticated = false;
myDataRef.unauth();
};
var authData = myDataRef.getAuth();
if (authData != null) {
$scope.authenticated = true;
}
}]);
controllers.controller('LoginCntrl', ['$scope', '$location', '$window', '$timeout', function($scope, $location, $window, $timeout) {
var myDataRef;
$scope.navigate = function(path) {
$location.path(path);
};
$scope.failed = false;
myDataRef = new $window.Firebase('https://wineapp.firebaseio.com');
$scope.login = function() {
myDataRef.authWithPassword({
email: $scope.email,
password: $scope.password
}, function(error, authData) {
$timeout(function() {
if (! error) {
$scope.navigate('/');
} else {
$scope.failed = true;
$scope.password = '';
}
});
});;
};
}]);
controllers.controller('WineriesCntrl', ['$scope', '$location', '$window', '$timeout', function($scope, $location, $window, $timeout) {
var myDataRef;
$scope.wineries;
$scope.navigate = function(path) {
$location.path(path);
};
myDataRef = new $window.Firebase('https://wineapp.firebaseio.com');
myDataRef.child('wineries').once('value', function(snapshot) {
$timeout(function() {
$scope.wineries = Object.keys(snapshot.val()).map(function(key) {
return {key: key, val: snapshot.val()[key]};
...