Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modularizing the code, using ui-router, demonstrating DRY tests, etc. #88

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .bowerrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"directory" : "vendor"
}
"directory": "bower_components"
}
12 changes: 2 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,5 @@ npm-debug.log

test/test-results.xml

vendor/angular-cookies/
vendor/angular-mocks/
vendor/angular-resource/
vendor/angular-sanitize/
vendor/angular/
vendor/bootstrap-less-themes/
vendor/bootstrap/
vendor/console-polyfill/
vendor/font-awesome/
vendor/jquery/
# Bower stuff.
bower_components/
53 changes: 40 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,38 @@

[AngularJS](http://angularjs.org) + [Brunch](http://brunch.io)

#### ** MAJOR UPDATES **
v0.4.1 Brings with it some major changes. If you're upgrading from a previous release,
please run `./scripts/init.sh` and remove any bower components from `vendor`. Bower
now uses the `bower_components` directory.

Features:
* Coffeescript / Jade / Less / Stylus automatically compiled on save
* auto-reload during development saves you from manually refreshing the page
* Javascript / CSS minification for production
* [karma](https://github.com/karma-runner/karma) integration for
unit tests
* Bootstrap integration with themes.
* Source map support
* Modularized code, see /app/sections
* angular/ui-router for more flexible routing

## Why modularize?

This "modularized" version is intended to be as simple as possible while laying down patterns that, if followed, will create an easily-maintained complex application. The original Angular-Seed entices one down the path of code segregated by type (controllers, views, etc.) rather than by feature (todo, view1, view2). Misko recommends organizing code around features (see [this](http://www.youtube.com/watch?feature=player_embedded&v=E87rXWE62WU#t=106s) 10/27/13 presentation).

Modularized code is better for
* unit testing
* working with larger teams (to not step on each others’ work)
* preparing for the future because modules will be able to be lazy-loaded and so this structure will be either required or firmly recommended

## What, exactly, is different in the modularized code?
Differences
* Instead of one controller, one partials folder, one module, there are several
* top level ones under /app
* lower-level ones under /app/sections
* (to make that work, karma.conf.js and config.coffee had to be changed, to pick up and integrate the files from more locations)
* Instead of using the $routeProvider, it uses angular-ui-router to allow output to multiple named views, nested views, etc. Routing and ng-view was mentioned by many online as pain points for larger apps. This arrangement should be much better.

## Alternate Versions

Expand All @@ -22,6 +47,9 @@ Features:
- [brunch-on-asteroids](https://github.com/exlee/brunch-on-asteroids)
by [@exlee](https://github.com/exlee) - A minimalistic version that adds Generators,
Bootswatch themes, D3, and more.
- [angular-brunch-seed-modularized](https://github.com/sanfordredlich/angular-brunch-seed-modularized)
by [@sanfordredlich](https://github.com/sanfordredlich) - Demonstrates a modular
design, consistent with best practices and better suited for larger projects

## How to use angular-brunch-seed

Expand All @@ -32,7 +60,7 @@ Features:

Or if you have **Brunch** installed run:

`brunch new myapp --skeleton https://github.com/scotch/angular-brunch-seed`
`brunch new https://github.com/scotch/angular-brunch-seed myapp`

You must also install packages using bower. Either

Expand All @@ -41,7 +69,7 @@ bower install
```
or
```
./node_modules/.bin/bower
./node_modules/.bin/bower install
```

*NOTE:* Depending upon your connection and processor speed the build can take
Expand Down Expand Up @@ -110,11 +138,10 @@ and run `bower install`. The component will be added to the `vendor` directory.
### Running unit tests

* `./scripts/test.sh` to run unit tests with [karma](https://github.com/karma-runner/karma)
* Open the browser you would like to test to [http://localhost:3334](http://localhost:3334)

Notes:

- Testacular will run tests on save. To insure that changes are saved be sure
- Karma will run tests on save. To insure that changes are saved be sure
to have `./script/server.sh` or `./script/development.sh` running in the console.
- Set the browsers that you would like to target in the `/test/karma.conf.js` file
E.g. `browser = ["ChromeCanary", "Firefox"]`
Expand Down Expand Up @@ -155,8 +182,6 @@ git pull origin master

assets --> a place for static assets. These files will be copied to
the public directory un-modified.
font/ --> [fontawesome](http://fortawesome.github.com/Font-Awesome/) rendering icons
fontawesome-webfont.*
img/ --> image files
partials/ --> angular view partials (partial HTML templates)
nav.html If you are using HTML you may modify these files directly.
Expand Down Expand Up @@ -186,6 +211,9 @@ git pull origin master
index.jade --> Index file. This will be converted to assets/index.html on save
init.coffee --> application bootstrap

bower_components/ --> The bower_components dirctory is populated by Bower.
It contains Angular, Bootstrap Font-Awesome
and other utility files.
node_modules --> NodeJS modules

scripts/ --> handy shell scripts
Expand All @@ -207,14 +235,13 @@ git pull origin master
filters.spec.js --> specs for filters
services.spec.js --> specs for services
vendor/
test-results.xml --> Testacular test resuls
karma-e2e.conf.js --> Testacular end-to-end tests config
karma.conf.js --> Testacular unit tests config
test-results.xml --> Karma test resuls
karma-e2e.conf.js --> Karma end-to-end tests config
karma.conf.js --> Karma unit tests config

vendor/ --> The vendor dirctory is populated by Bower.
It contains Angular, Bootstrap Font-Awesome
and other utility files.
component.json --> Bower component config
vendor/ --> The vendor directory is can be used for 3rd Party libraries.
Any files located in this directory will be included in js/vendor.js
bower.json --> Bower component config
config.coffee --> Brunch config
package.json --> node modules config

Expand Down
48 changes: 36 additions & 12 deletions app/app.coffee
Original file line number Diff line number Diff line change
@@ -1,31 +1,55 @@

'use strict'

# Declare app level module which depends on filters, and services
App = angular.module('app', [
#used for angular-ui-router
'ui.state'

'ngCookies'
'ngResource'
'app.controllers'
'app.directives'
'app.filters'
'app.services'
'partials'
'navbar.partials'
'todo.partials'
'app.todo.controllers'
'view1.partials'
'app.view1.controllers'
'view2.partials'
'app.view2.controllers'
])

App.config([
'$routeProvider'
'$locationProvider'
'$stateProvider'
'$urlRouterProvider'

($routeProvider, $locationProvider, config) ->
($stateProvider, $urlRouterProvider) ->

$routeProvider
# default to the todo page
$urlRouterProvider.otherwise("/todo")

$stateProvider

.when('/todo', {templateUrl: '/partials/todo.html'})
.when('/view1', {templateUrl: '/partials/partial1.html'})
.when('/view2', {templateUrl: '/partials/partial2.html'})
.state('todo',
url: "/todo"
views:
"main-content":
templateUrl: "/todo/todo.html"
)

# Catch all
.otherwise({redirectTo: '/todo'})
.state('view1',
url: "/view1"
views:
"main-content":
templateUrl: "/view1/partial1.html"
)

# Without server side support html5 must be disabled.
$locationProvider.html5Mode(false)
.state('view2',
url: "/view2"
views:
"main-content":
templateUrl: "/view2/partial2.html"
)
])
39 changes: 22 additions & 17 deletions app/index.jade
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,7 @@ html(lang='en', ng-app='app')
meta(name='author', content='')
title(ng-bind-template='{{pageTitle}}')
link(rel='stylesheet', href='/css/app.css')
//-script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js')
//if lte IE 7
script(src='http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js')
//if lte IE 8
script(src='//html5shiv.googlecode.com/svn/trunk/html5.js')
script
window.brunch = window.brunch || {};
window.brunch['auto-reload'] = {
enabled: true
};
script(src='/js/auto-reload.js')
script(src='/js/vendor.js')
script(src='/js/partials.js')
script(src='/js/app.js')

body(ng-controller='AppCtrl')
.wrapper
.navbar.navbar-static-top
Expand All @@ -33,14 +20,32 @@ html(lang='en', ng-app='app')
span.icon-bar
a(href='/').brand Angular Brunch Seed
.nav-collapse
div(ng-include="'/partials/nav.html'")
div(ng-include="'/navbar/nav.html'")
.container.main-content
div(ng-view)
div(ui-view="main-content")
div Angular Brunch seed app: v<span app-version></span>
.push

footer.footer
.container
p
small
a(href='https://github.com/scotch/angular-brunch-seed') angular-brunch-seed | source
a(href='https://github.com/scotch/angular-brunch-seed.git') angular-brunch-seed (modularized) | source

//-script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js')
//if lte IE 7
script(src='http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js')
//if lte IE 8
script(src='//html5shiv.googlecode.com/svn/trunk/html5.js')
script.
window.brunch = window.brunch || {};
window.brunch['auto-reload'] = {
enabled: true
};
script(src='/js/auto-reload.js')
script(src='/js/vendor.js')
script(src='/js/navbar.partials.js')
script(src='/js/todo.partials.js')
script(src='/js/view1.partials.js')
script(src='/js/view2.partials.js')
script(src='/js/app.js')
54 changes: 3 additions & 51 deletions app/scripts/controllers.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ angular.module('app.controllers', [])
'$rootScope'

($scope, $location, $resource, $rootScope) ->

$scope.appData = {}

# Uses the url to determine if the selected
# menu item should have the class active.
Expand All @@ -32,54 +34,4 @@ angular.module('app.controllers', [])
return 'active'
else
return ''
])

.controller('MyCtrl1', [
'$scope'

($scope) ->
$scope.onePlusOne = 2
])

.controller('MyCtrl2', [
'$scope'

($scope) ->
$scope
])

.controller('TodoCtrl', [
'$scope'

($scope) ->

$scope.todos = [
text: "learn angular"
done: true
,
text: "build an angular app"
done: false
]

$scope.addTodo = ->
$scope.todos.push
text: $scope.todoText
done: false

$scope.todoText = ""

$scope.remaining = ->
count = 0
angular.forEach $scope.todos, (todo) ->
count += (if todo.done then 0 else 1)

count

$scope.archive = ->
oldTodos = $scope.todos
$scope.todos = []
angular.forEach oldTodos, (todo) ->
$scope.todos.push todo unless todo.done

])

])
File renamed without changes.
37 changes: 37 additions & 0 deletions app/sections/home/scripts/home.controllers.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
angular.module('app.home.controllers', [])

.controller('TodoCtrl', [
'$scope'

($scope) ->

$scope.todos = [
text: "learn angular"
done: true
,
text: "build an angular app"
done: false
]

$scope.addTodo = ->
$scope.todos.push
text: $scope.todoText
done: false

$scope.todoText = ""

$scope.remaining = ->
count = 0
angular.forEach $scope.todos, (todo) ->
count += (if todo.done then 0 else 1)

count

$scope.archive = ->
oldTodos = $scope.todos
$scope.todos = []
angular.forEach oldTodos, (todo) ->
$scope.todos.push todo unless todo.done

])

File renamed without changes.
16 changes: 16 additions & 0 deletions app/sections/todo/partials/todo.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
div(ng-app='ng-app')
h2 Todo
div(ng-controller='TodoCtrl')
span {{remaining()}} of {{todos.length}} remaining
| [
a(href='', ng-click='archive()') archive
| ]
ul.unstyled
li(ng-repeat='todo in todos')
label(class='checkbox inline')
input(type='checkbox', ng-model='todo.done')
span(class='done{{todo.done}}') {{todo.text}}
form(class='form-inline', ng-submit='addTodo()')
p
input(type='text', ng-model='todoText', size='30', placeholder='add new todo here')
input.btn.btn-primary(type='submit', value='add')
Loading