title: BucketList App author: name: Tom Wilson twitter: twilson63 url: http://jackhq.com output: index.html controls: true
--
--
--
We are going to install nodejs if you do not already have nodejs download and install from http://nodejs.org - then we will create a new directory and a simple index.html
file. This file will link to cdnjs for all of our dependencies.
--
# nodejs required
npm i w3 -g
mkdir bucket-list-app
cd bucket-list-app
touch index.html
--
edit index.html
<!doctype html>
<html>
<head>
<title>Foo</title>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
</head>
<body>
<h1>Hello World</h1>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/pouchdb/3.4.0/pouchdb.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
</body>
</html>
--
So lets validate our setup, in order to do this, we need to install tap:
npm i ng-adventure -g
ng-adventure
ng-adventure verify
--
w3
open browser http://localhost:3000
--
In this exercise we are going to create an angular app and setup two databinding to confirm we have everything setup correctly.
--
On the body element of your index.html file add the ng-app
attribute.
--
Inside the body element remove <h1>Hello World</h1>
and add the following:
<div ng-init="title = 'My Bucket List'"></div>
<h1>{{title}}</h1>
--
w3
Point Browser to http://localhost:3000
--
Now that we have a working angularjs application, lets go ahead and build out the routing and templates.
--
First we will modify the index.html file to use the <ui-view></ui-view>
element.
Modify:
<body ng-app="App">
Remove:
<div ng-init="title = 'My Bucket List'"></div>
<h1>{{title}}</h1>
Add:
<ui-view></ui-view>
Also add the app.js file at the end of the body
<script src="app.js"></script>
--
Next we need to create an app.js
file to contain our routing information.
app.js
angular.module('App', ['ui.router'])
.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/',
templateUrl: '/templates/main.html'
})
--
Now we need to create a templates directory and main.html file
mkdir templates
touch main.html
--
Edit the main.html and add this:
<h1>My Bucket List</h1>
--
In this exercise we are going to creat a form for our bucket list. We will
link the form to our main page by adding an Add
button.
--
cd templates
touch add.html
--
- Title - input
- Description - textarea
- Save Button
--
<div class="container">
<h2>Add</h2>
<form ng-submit="add(thing)">
<fieldset>
<label>Title</label>
<input class="u-full-width" type="text" ng-model="thing.title">
</fieldset>
<fieldset>
<label>Description</label>
<textarea class="u-full-width" ng-model="thing.description"></textarea>
</fieldset>
<button class="button-primary u-pull-right">Save</button>
<a class="button u-pull-right" ui-sref="index">Cancel</a>
</form>
</div>
--
angular.module('App', ['ui.router'])
.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/',
templateUrl: '/templates/main.html'
})
.state('add', {
url: '/add',
templateUrl: '/templates/add.html'
})
})
--
add.html template
<h1>My Bucket List</h1>
<a class="button button-primary" ui-sref="add">Add</a>
--
go to our add form
--
In this exercise we are going to setup a simple service to store our bucket list items:
--
Create a file called services.js
** Hint make sure you are in your project root directory
--
angular.module('App')
.factory('bucketlist', function() {
var db = PouchDB('bucketlist')
return {
put: function(thing) {
return db.put(thing)
},
get: function(id) {
return db.get(id)
},
all: function() {
return db.allDocs({ include_docs: true})
.then(function(res) {
return _(res.rows).pluck('doc')
})
}
}
})
--
Inject the bucketlist service into your add controller, ok so we don't have a add controller, we need to create one:
Create a file called controllers.js
angular.module('App')
.controller('AddController', function($scope, bucketlist, $state) {
$scope.add = function(thing) {
thing._id = (new Date()).toISOString()
bucketlist.put(thing)
.then(function(res) {
$state.go('main')
})
}
})
--
Now we need to attach the controller to our route in app.js
angular.module('App', ['ui.router'])
.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/',
templateUrl: '/templates/main.html'
})
.state('add', {
url: '/add',
templateUrl: '/templates/add.html',
controller: 'AddController'
})
})
--
Finally we need to include the new js files in our index.html
<!doctype html>
<html>
<head>
<title>Foo</title>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="stylesheet" href="/custom.css">
</head>
<body>
<h1>Hello World</h1>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.js"></script>
<script src="app.js"></script>
<script src="services.js"></script>
<script src="controllers.js"></script>
</body>
</html>
--
verify via server
w3
--
Now that we have our form adding data to our service, we want to redirect the user back to the main page and show the new item in a list.
--
index.html
<!doctype html>
<html>
<head>
<title>Foo</title>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="stylesheet" href="/custom.css">
</head>
<body>
<h1>Hello World</h1>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/pouchdb/3.4.0/pouchdb.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<script src="app.js"></script>
<script src="services.js"></script>
<script src="controllers.js"></script>
</body>
</html>
--
We need to inject the $state service in our add controller, then use the $state.go method to redirect to the main state.
--
controllers.js
angular.module('App')
.controller('AddController', function($scope, bucketlist, $state) {
$scope.add = function(thing) {
thing._id = (new Date()).toISOString()
bucketlist.put(thing)
.then(function(res) {
$state.go('main')
})
}
})
--
Now we need to create a main controller and attach it to our route
controllers.js
angular.module('App')
.controller('AddController', function($scope, bucketlist, $state) {
$scope.add = function(thing) {
bucketlist.add(thing)
$state.go('main')
}
})
.controller('ListController', function($scope, bucketlist) {
bucketlist.all().then(function(things){
$scope.$apply(function() {
$scope.bucketlist = things
})
})
})
--
app.js
angular.module('App', ['ui.router'])
.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/',
templateUrl: '/templates/main.html',
controller: 'ListController'
})
.state('add', {
url: '/add',
templateUrl: '/templates/add.html',
controller: 'AddController'
})
})
--
Now that we have our list, lets render it to our main template using ng-repeat
--
main.html
<div class="container">
<h1>My Bucket List</h1>
<a class="button button-primary" ui-sref="add">Add</a>
<ul>
<li ng-repeat="thing in bucketlist">
{{thing.title}}
</li>
</ul>
</div>
--
Let restart run the server and see
--
List create a show page to display our bucket list item
- create a new route called show
- create a new templates called show.html
- create a new controller called ShowController
--
angular.module('App', ['ui.router'])
.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/',
templateUrl: '/templates/main.html',
controller: 'MainController'
})
.state('add', {
url: '/add',
templateUrl: '/templates/add.html',
controller: 'AddController'
})
.state('show', {
url: '/show/:id',
templateUrl: '/templates/show.html',
controller: 'ShowController'
})
})
--
<div class="container">
<h2>{{thing.title}}</h2>
<p>{{thing.description}}</p>
<a class="button" ui-sref="edit({ id: thing._id})">Edit</a>
</div>
--
angular.module('App')
.controller('AddController', function($scope, bucketlist, $state) {
$scope.add = function(thing) {
thing._id = (new Date()).toISOString()
bucketlist.put(thing)
.then(function(res) {
$state.go('main')
})
}
})
.controller('ListController', function($scope, bucketlist) {
bucketlist.all().then(function(things){
$scope.$apply(function() {
$scope.bucketlist = things
})
})
})
.controller('ShowController', function($scope, bucketlist, $stateParams) {
bucketlist.get($stateParams.id).then(function(thing) {
$scope.$apply(function() {
$scope.thing = thing
})
})
})
--
<div class="container">
<h1>My Bucket List</h1>
<a class="button button-primary" ui-sref="add">Add</a>
<ul>
<li ng-repeat="thing in bucketlist">
<a ui-sref="show({ id: thing._id })">
{{thing.title}}
</a>
</li>
</ul>
</div>
--
Lets create a Edit form
- create a new route called edit
- create a new templates called edit.html
- create a new controller called EditController
- create a button on show template to direct to Edit Route
--
angular.module('App', ['ui.router'])
.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/',
templateUrl: '/templates/main.html',
controller: 'MainController'
})
.state('add', {
url: '/add',
templateUrl: '/templates/add.html',
controller: 'AddController'
})
.state('show', {
url: '/show/:id',
templateUrl: '/templates/show.html',
controller: 'ShowController'
})
.state('edit', {
url: '/edit/:id',
templateUrl: '/templates/edit.html',
controller: 'EditController'
})
})
--
<div class="container">
<h2>Edit</h2>
<form ng-submit="update(thing)">
<fieldset>
<label>Title</label>
<input class="u-full-width" type="text" ng-model="thing.title">
</fieldset>
<fieldset>
<label>Description</label>
<textarea class="u-full-width" ng-model="thing.description"></textarea>
</fieldset>
<button class="button-primary u-pull-right">Save</button>
<a class="button u-pull-right" ui-sref="index">Cancel</a>
</form>
</div>
--
angular.module('App')
.controller('AddController', function($scope, bucketlist, $state) {
$scope.add = function(thing) {
thing._id = (new Date()).toISOString()
bucketlist.put(thing)
.then(function(res) {
$state.go('main')
})
}
})
.controller('ListController', function($scope, bucketlist) {
bucketlist.all().then(function(things){
$scope.$apply(function() {
$scope.bucketlist = things
})
})
})
.controller('ShowController', function($scope, bucketlist, $stateParams) {
bucketlist.get($stateParams.id).then(function(thing) {
$scope.$apply(function() {
$scope.thing = thing
})
})
})
.controller('EditController', function($scope, bucketlist, $stateParams, $state) {
bucketlist.get($stateParams.id).then(function(thing) {
$scope.$apply(function() {
$scope.thing = thing
})
})
$scope.update = function(thing) {
bucketlist.put(thing)
.then(function(res) {
$state.go('show', { id: thing._id})
})
}
})
--
<div class="container">
<h2>{{thing.title}}</h2>
<p>{{thing.description}}</p>
<a class="button" ui-sref="edit({ id: thing._id})">Edit</a>
<a class="button" ui-sref="main">Bucket List</a>
</div>
--
Adding a couple of items
...
--
Lets create a filter
...
<li ng-repeat="thing in bucketlist | filter:thing">
<a ui-sref="show({ id: thing._id })">
--