Please refer to the instructions in the top level README.
Angular-phonecat is based in part on angular-seed and uses the following layout:
On the other hand, this project --following Brunch and to some extent angular-brunch-seed-- uses the following layout (some sections to be expanded later):
It should be emphasized that Brunch allows you to tailor this layout
to suit your preferences. For example, you can edit
to rename the
public directory or to specify how should files be
compiled or concatenated.
Serving the Application
Angular-phonecat provides a basic Node.js web server (in
scripts/web-server.js) and if you run it from the
you can access the application at
http://localhost:8000/app/index.html. However, you can use any
Brunch provides its own development server. You can start it from the command line with:
brunch watch --server
which can be shortened to
brunch w -s. However, we suggest you use
Brunch will watch the files in the project and re-compile whenever
necessary. In addition,
auto-reload-brunch will react to changes on
the web browser side.
Please refer to the Angular-phonecat README and the AngularJS Tutorial for details on the steps from the basic AngularJS viewpoint. In what follows, we highlight the differences between angular-phonecat and this project.
If you follow along by checking out each step, please remember that
when packages or components are added to
bower.json, you will need to run
npm install or
respectively, in order to add the parts to your environment.
Step-0 - Bootstrapping the App
At this stage, the simple
index.html is almost identical to the one
from the parent project. However, it is placed in
because it gets copied as-is to the
public directory. Note also
angular.js file, which you downloaded with Bower and then
vendor/scripts, has been copied to
bootstrap.css which you put in
You may want to experiment with
brunch build --optimize to verify
that the latter two files in the
public subdirectories have been
You can also verify that Brunch recompilation and browser reloading is working by doing the experiment suggested in this step of the AngularJS tutorial. Ensure you read and follow the Auto-Reload section in the main README.
Step-0a - Use Jade Templates
Step-1 - Static Item List
This step introduces some minor HTML and CSS changes:
index.jadegot an unordered list of two phones (and a title change)
app/styles/app.csswas added which only specified body padding.
Note that the latter CSS file gets concatenated at the end of
bootstrap.css to form
Step-2 - Angular ngRepeat Directive
Step-2 also incorporates unit testing. This is done through the
Karma test runner and the
development (BDD) framework. To support this, we added Karma as a
package.json and changed the
to start Karma.
karma.conf.js was adapted by using the
angular-mock.js files directly from the
subdirectory. After some experimentation (on Debian), we also
specified 'Firefox' and 'Chrome' (or
chromium) as browsers (now in
karma-shared.conf.js). Please refer to Karma
for more details on choices for your environment. For example, on
Debian, in order to run Chromium as Chrome, you'll need to use
test/unit/controllersSpec.js unit test specification is
identical to the one in angular-phonecat (but see below).
To run the unit tests, invoke
npm test. Karma will be watching your
source files as well, so that changes you make will trigger a re-test.
Step-2a - Use CoffeeScript
Step-3 - Interactive Search
In this step, a
filter is used to
allow the user to select a subset of records. This also demonstrates
data binding since the input box has the
ng-model attribute with
value query and the latter is used as the
to the filter.
app/index.html was changed in the original, so we only made
equivalent modifications to
Step-3 also introduces scenario testing (also referred to as
end-to-end testing in AngularJS documentation). To support this, we
added the original
config/karma-e2e.conf.js in the
and adapted it by changing the file extensions, browsers and proxy
port, and adding a
We also adapted
test/e2e/scenarios.js into an equivalent
In order to run the tests, you first need to have the Brunch server
running (i.e., do
npm start or
brunch w -s). Then, from another
karma start test/karma-e2e.conf.js
This is set up to run as a single shot rather than watch over files.
Angular-phonecat also includes a
test/e2e/runner.html which allows
running the scenario tests from an already open browser window. This
could perhaps be adapted to run from the
public directory (by
installing the original in
app/assets, but we have chosen not to do
so for the time being.
Step-4 - Ordering the List
This step adds a simple feature: a drop-down list to allow the user to select the order in which the items are displayed. An 'age' property is added to the model to support both alphabetical and aged ordering. An additional unit test and a couple of end-to-end tests are present as well.
Step-5 - XHR and Dependency Injection
At this stage, the hard-coded data in the controller is replaced by a
phones.json file. We placed it under
that Brunch will copy it into
public/phones. The file is loaded
using the $http service,
which is passed into the
PhoneListCtrl controller using dependency
This process is mocked in the unit tests by using the inject function to supply fixed data and by instantiating the controller before each test. The scenario test only required adjustment to the expected item counts.
Step-6 Add Images and Links
In this step, thumbnail images of the phones were added to the list.
We added the JPEGs in
they would get copied to
modified to include IMG tags (and also links to future detail pages.
app.css file was changed to size the thumbnails and to better
style the page. Finally, a third end-to-end test was added to
Step-6a - Use Stylus
Now that we have a not so trivial stylesheet, we can introduce a
dynamic stylesheet language processor. I've chosen
Stylus and this step renames
app.styl for this purpose.
The resulting file is not much different and doesn't take advantage of
more advanced features of Stylus. You'll also need to install
stylus-brunch (which has been added to
Step-7 - Routing and App Partitioning
This step adds
app/app.coffee which uses the
service to handle application routes.
On the HTML side, most of the body of
app/index.jade was split and
partials/phone-list.jade. The former was replaced by a
div tag with an
attribute. A new file,
partials/phone-detail.jade, is a stub for a
detail view. A new controller,
PhoneDetailCtrl was added to
On the testing front, a unit test for the new controller was also
stubbed out, but
scenarios.coffee now verifies that the
passed down from the list to the detail stub. In addition, an
end-to-end test was added to check that the root URL gets redirected
Step-8 - Details View
In this step we fill out the stubs from the previous one. To provide
detailed phone information, we copied JSON files and JPEG images from
the original project to the
app/assets/img/phones directories, respectively.
app/partials/phone-detail.jade was fleshed out to display the
detailed information and images and the 'app/styles/app.styl`
stylesheet was updated to improve the esthetics.
The unit test stub for PhoneDetailCtrl was also changed to actually
verify proper fetching of (mocked) detail data. Similarly, the phone
detail scenario test now checks the phone name (rather than
Step-9 - Custom Filter
This step adds a custom filter to display Boolean values using Unicode
symbols. The filter is defined in
this module is injected into
phone-detail.jade template was changed to use the filter in a couple
of items. A unit test to verify the filter was added with
Step-10 - Event Handlers
A simple click event handler was added through an
attribute in the list of secondary images in the
partial. This invokes a
setImage function that was coded as part of
To verify this, one unit test and two end-to-end tests were also written.
Step-11 - Custom Service
In this step of the original tutorial, the $http service introduced in step-5 was replaced by a custom service using the $resource factory. This doesn't affect the application's external behavior in any way, but makes it easier to program --since it is a higher-level API-- or to modify, e.g., by replacing the backend.
To implement the factory we first had to add
bower.json. The custom service was then defined in
app/scripts/services.coffee and injected into the application in
app/app.coffee. The service replaced the $http calls in
test/karma.conf.js was modified to generalize the
AngularJS files needed. The
controllersSpec.coffee was also
modified, as per the original tutorial.