From 5050dd504bd57a133f064eec5ad1452fc6ecd0e2 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Sun, 27 Mar 2016 21:32:36 +0300 Subject: [PATCH 1/6] docs(tutorial): update to use `v1.5.x` and best practices This is a major re-structuring of the tutorial app's codebase, aiming at applying established best practices (in terms of file naming/layout and code organization) and utilizing several new features and enhancements (most notably components) introduced in recent versions of Angular (especially v1.5). Apart from the overall changes, two new chapters were introduced: one on components and one on code organization. -- In the process, several other things were (incidentally) taken care of, including: * Dependencies were upgraded to latest versions. * Animations were polished. * Outdated links were updated. * The app's base URL was changed to `/` (instead of `/app/`). BTW, this has been tested with the following versions of Node (on Windows 10) and everything worked fine: * 0.11.16 * 4.2.6 * 4.4.2 * 5.10.0 -- This was inspired by (and loosely based on) #13834. Again, mad props to @teropa for leading the way :) -- **Note:** The old version of the tutorial, that is compatible with Angular version 1.4 or older, has been saved on the `pre-v1.5.0-snapshot` branch of [angular-phonecat](https://github.com/angular/angular-phonecat). The `v1.4.x` version of the tutorial should be pointed to that branch instead of `master`. -- Related to angular/angular-phonecat#326. Related to angular/angular-seed#329. Related to angular/angular-seed#333. --- Fixes #12755 Fixes #13312 Fixes #13623 Fixes #13632 Closes #8952 Closes #11726 Closes #12946 Closes #12947 Closes #13198 Closes #13284 Closes #13834 Closes #14178 Closes #14223 --- docs/content/tutorial/index.ngdoc | 202 +++--- docs/content/tutorial/step_00.ngdoc | 165 ++--- docs/content/tutorial/step_01.ngdoc | 14 +- docs/content/tutorial/step_02.ngdoc | 284 +++++---- docs/content/tutorial/step_03.ngdoc | 362 ++++++----- docs/content/tutorial/step_04.ngdoc | 361 +++++++---- docs/content/tutorial/step_05.ngdoc | 315 ++++------ docs/content/tutorial/step_06.ngdoc | 257 ++++++-- docs/content/tutorial/step_07.ngdoc | 495 +++++++-------- docs/content/tutorial/step_08.ngdoc | 206 ++----- docs/content/tutorial/step_09.ngdoc | 432 ++++++++++--- docs/content/tutorial/step_10.ngdoc | 255 ++++---- docs/content/tutorial/step_11.ngdoc | 329 ++++------ docs/content/tutorial/step_12.ngdoc | 578 ++++-------------- docs/content/tutorial/step_13.ngdoc | 321 ++++++++++ docs/content/tutorial/step_14.ngdoc | 565 +++++++++++++++++ docs/content/tutorial/the_end.ngdoc | 19 +- docs/img/tutorial/tutorial_03.png | Bin 125034 -> 0 bytes docs/img/tutorial/tutorial_05.png | Bin 40911 -> 125034 bytes .../{tutorial_04.png => tutorial_06.png} | Bin docs/img/tutorial/tutorial_07.png | Bin 0 -> 40911 bytes .../{tutorial_05.pptx => tutorial_07.pptx} | Bin ...ial_07_final.png => tutorial_09_final.png} | Bin ..._08-09_final.png => tutorial_10_final.png} | Bin ..._10-11_final.png => tutorial_12_final.png} | Bin 25 files changed, 3012 insertions(+), 2148 deletions(-) create mode 100644 docs/content/tutorial/step_13.ngdoc create mode 100644 docs/content/tutorial/step_14.ngdoc delete mode 100644 docs/img/tutorial/tutorial_03.png rename docs/img/tutorial/{tutorial_04.png => tutorial_06.png} (100%) create mode 100644 docs/img/tutorial/tutorial_07.png rename docs/img/tutorial/{tutorial_05.pptx => tutorial_07.pptx} (100%) rename docs/img/tutorial/{tutorial_07_final.png => tutorial_09_final.png} (100%) rename docs/img/tutorial/{tutorial_08-09_final.png => tutorial_10_final.png} (100%) rename docs/img/tutorial/{tutorial_10-11_final.png => tutorial_12_final.png} (100%) diff --git a/docs/content/tutorial/index.ngdoc b/docs/content/tutorial/index.ngdoc index 78e1cfee6172..32e26e17981c 100644 --- a/docs/content/tutorial/index.ngdoc +++ b/docs/content/tutorial/index.ngdoc @@ -6,12 +6,12 @@ # PhoneCat Tutorial App A great way to get introduced to AngularJS is to work through this tutorial, which walks you through -the construction of an AngularJS web app. The app you will build is a catalog that displays a list +the construction of an Angular web app. The app you will build is a catalog that displays a list of Android devices, lets you filter the list to see only devices that interest you, and then view details for any device. -demo
-application running in the browser +demo application running in the browser Follow the tutorial to see how Angular makes browsers smarter — without the use of native extensions or plug-ins: @@ -28,10 +28,11 @@ When you finish the tutorial you will be able to: * Create a dynamic application that works in all modern browsers. * Use data binding to wire up your data model to your views. * Create and run unit tests, with Karma. -* Create and run end to end tests, with Protractor. -* Move application logic out of the template and into Controllers. +* Create and run end-to-end tests, with Protractor. +* Move application logic out of the template and into components and controllers. * Get data from a server using Angular services. -* Apply animations to your application, using ngAnimate. +* Apply animations to your application, using the `ngAnimate` module. +* Structure your Angular applications in a modular way that scales well for larger projects. * Identify resources for learning more about AngularJS. The tutorial guides you through the entire process of building a simple application, including @@ -42,16 +43,18 @@ You can go through the whole tutorial in a couple of hours or you may want to sp really digging into it. If you're looking for a shorter introduction to AngularJS, check out the {@link misc/started Getting Started} document. -# Get Started + +# Environment Setup The rest of this page explains how you can set up your local machine for development. -If you just want to read the tutorial then you can just go straight to the first step: +If you just want to _read_ the tutorial, you can go straight to the first step: [Step 0 - Bootstrapping](tutorial/step_00). -# Working with the code + +## Working with the Code You can follow along with this tutorial and hack on the code in the comfort of your own computer. -In this way you can get hands-on practice of really writing AngularJS code and also on using the +This way, you can get hands-on practice of really writing Angular code and also on using the recommended testing tools. The tutorial relies on the use of the [Git][git] versioning system for source code management. @@ -62,10 +65,11 @@ a few git commands. ### Install Git You can download and install Git from http://git-scm.com/download. Once installed, you should have -access to the `git` command line tool. The main commands that you will need to use are: +access to the `git` command line tool. The main commands that you will need to use are: + +* `git clone ...`: Clone a remote repository onto your local machine. +* `git checkout ...`: Check out a particular branch or a tagged version of the code to hack on. -- `git clone ...` : clone a remote repository onto your local machine -- `git checkout ...` : check out a particular branch or a tagged version of the code to hack on ### Download angular-phonecat @@ -73,13 +77,14 @@ Clone the [angular-phonecat repository][angular-phonecat] located at GitHub by r command: ``` -git clone --depth=14 https://github.com/angular/angular-phonecat.git +git clone --depth=16 https://github.com/angular/angular-phonecat.git ``` -This command creates the `angular-phonecat` directory in your current directory. +This command creates an `angular-phonecat` sub-directory in your current directory. -
The `--depth=14` option just tells Git to pull down only the last 14 commits. This makes the -download much smaller and faster. +
+ The `--depth=16` option tells Git to pull down only the last 16 commits. + This makes the download much smaller and faster.
Change your current directory to `angular-phonecat`. @@ -88,16 +93,16 @@ Change your current directory to `angular-phonecat`. cd angular-phonecat ``` -The tutorial instructions, from now on, assume you are running all commands from the +The tutorial instructions, from now on, assume you are running all commands from within the `angular-phonecat` directory. ### Install Node.js -If you want to run the preconfigured local web-server and the test tools then you will also need -[Node.js v0.10.27+][node]. +If you want to run the preconfigured local web server and the test tools then you will also need +[Node.js v4+][node]. -You can download a Node.js installer for your operating system from http://nodejs.org/download/. +You can download a Node.js installer for your operating system from https://nodejs.org/en/download/. Check the version of Node.js that you have installed by running the following command: @@ -105,7 +110,7 @@ Check the version of Node.js that you have installed by running the following co node --version ``` -In Debian based distributions, there is a name clash with another utility called `node`. The +In Debian based distributions, there might be a name clash with another utility called `node`. The suggested solution is to also install the `nodejs-legacy` apt package, which renames `node` to `nodejs`. @@ -115,12 +120,9 @@ nodejs --version npm --version ``` - -
If you need to run different versions of node.js - in your local environment, consider installing - - Node Version Manager (nvm) - . +
+ If you need to run different versions of Node.js in your local environment, consider installing + [Node Version Manager (nvm)][nvm] or [Node Version Manager (nvm) for Windows][nvm-windows].
Once you have Node.js installed on your machine, you can download the tool dependencies by running: @@ -129,30 +131,32 @@ Once you have Node.js installed on your machine, you can download the tool depen npm install ``` -This command reads angular-phonecat's `package.json` file and downloads the following tools -into the `node_modules` directory: +This command reads angular-phonecat's `package.json` file and downloads the following tools into the +`node_modules` directory: -- [Bower][bower] - client-side code package manager -- [Http-Server][http-server] - simple local static web server -- [Karma][karma] - unit test runner -- [Protractor][protractor] - end to end (E2E) test runner +* [Bower][bower] - client-side code package manager +* [Http-Server][http-server] - simple local static web server +* [Karma][karma] - unit test runner +* [Protractor][protractor] - end-to-end (E2E) test runner -Running `npm install` will also automatically use bower to download the Angular framework into the +Running `npm install` will also automatically use bower to download the AngularJS framework into the `app/bower_components` directory.
Note the angular-phonecat project is setup to install and run these utilities via npm scripts. This means that you do not have to have any of these utilities installed globally on your system - to follow the tutorial. See **Installing Helper Tools** below for more information. + to follow the tutorial. See [Installing Helper Tools](tutorial/#install-helper-tools-optional-) + below for more information.
The project is preconfigured with a number of npm helper scripts to make it easy to run the common tasks that you will need while developing: -- `npm start` : start a local development web-server -- `npm test` : start the Karma unit test runner -- `npm run protractor` : run the Protractor end to end (E2E) tests -- `npm run update-webdriver` : install the drivers needed by Protractor +* `npm start`: Start a local development web server. +* `npm test`: Start the Karma unit test runner. +* `npm run protractor`: Run the Protractor end-to-end (E2E) tests. +* `npm run update-webdriver`: Install the drivers needed by Protractor. + ### Install Helper Tools (optional) @@ -167,7 +171,7 @@ For instance, to install the Bower command line executable you would do: sudo npm install -g bower ``` -*(Omit the sudo if running on Windows)* +_(Omit the sudo if running on Windows)_ Then you can run the bower tool directly, such as: @@ -176,10 +180,10 @@ bower install ``` -### Running Development Web Server +### Running the Development Web Server While Angular applications are purely client-side code, and it is possible to open them in a web -browser directly from the file system, it is better to serve them from a HTTP web server. In +browser directly from the file system, it is better to serve them from an HTTP web server. In particular, for security reasons, most modern browsers will not allow JavaScript to make server requests if the page is loaded directly from the file system. @@ -190,70 +194,71 @@ application during development. Start the web server by running: npm start ``` -This will create a local webserver that is listening to port 8000 on your local machine. -You can now browse to the application at: - -``` -http://localhost:8000/app/index.html -``` +This will create a local web server that is listening to port 8000 on your local machine. +You can now browse to the application at http://localhost:8000/index.html.
-To serve the web app on a different IP address or port, edit the "start" script within package.json. -You can use `-a` to set the address and `-p` to set the port. + To serve the web app on a different IP address or port, edit the "start" script within + `package.json`. You can use `-a` to set the address and `-p` to set the port.
+ ### Running Unit Tests We use unit tests to ensure that the JavaScript code in our application is operating correctly. -Unit tests focus on testing small isolated parts of the application. The unit tests are kept in the -`test/unit` directory. +Unit tests focus on testing small isolated parts of the application. The unit tests are kept in test +files (specs) side-by-side with the application code. This way it's easier to find them and keep +them up-to-date with the code under test. It also makes refactoring our app structure easier, since +tests are moved together with the source code. The angular-phonecat project is configured to use [Karma][karma] to run the unit tests for the -application. Start Karma by running: +application. Start Karma by running: ``` npm test ``` -This will start the Karma unit test runner. Karma will read the configuration file at -`test/karma.conf.js`. This configuration file tells Karma to: +This will start the Karma unit test runner. Karma will read the configuration file `karma.conf.js`, +located at the root of the project directory. This configuration file tells Karma to: -- open up a Chrome browser and connect it to Karma -- execute all the unit tests in this browser -- report the results of these tests in the terminal/command line window -- watch all the project's JavaScript files and re-run the tests whenever any of these change +* Open up a Chrome browser and connect it to Karma. +* Execute all the unit tests in this browser. +* Report the results of these tests in the terminal/command line window. +* Watch all the project's JavaScript files and re-run the tests whenever any of these change. It is good to leave this running all the time, in the background, as it will give you immediate feedback about whether your changes pass the unit tests while you are working on the code. -### Running End to End Tests +### Running E2E Tests -We use End to End tests to ensure that the application as a whole operates as expected. -End to End tests are designed to test the whole client side application, in particular that the -views are displaying and behaving correctly. It does this by simulating real user interaction with -the real application running in the browser. +We use E2E (end-to-end) tests to ensure that the application as a whole operates as expected. +E2E tests are designed to test the whole client-side application, in particular that the views are +displaying and behaving correctly. It does this by simulating real user interaction with the real +application running in the browser. -The End to End tests are kept in the `test/e2e` directory. +The E2E tests are kept in the `e2e-tests` directory. -The angular-phonecat project is configured to use [Protractor][protractor] to run the End to End -tests for the application. Protractor relies upon a set of drivers to allow it to interact with -the browser. You can install these drivers by running: +The angular-phonecat project is configured to use [Protractor][protractor] to run the E2E tests for +the application. Protractor relies upon a set of drivers to allow it to interact with the browser. +You can install these drivers by running: ``` npm run update-webdriver ``` -*(You should only need to do this once.)* +
+ You don't have to manually run this command. Our npm scripts are configured so that it will be + automatically executed as part of the command that runs the E2E tests. +
+ +
+ Under the hood, Protractor uses the [Selenium Stadalone Server][selenium], which in turn requires + the [Java Development Kit (JDK)][jdk] to be installed on your local machine. Check this + by running `java -version` from the command line. -You will need to have Java present on your dev machine to allow the Selenium standalone to be started. -Check if you already have java installed by opening a terminal/command line window and typing -''' -java -version -''' -If java is already installed and exists in the PATH then you will be shown the version installed, -if, however you receive a message that "java is not recognized as an internal command or external -command" you will need to install [java]. + If JDK is not already install, you can download it [here][jdk-download]. +
Since Protractor works by interacting with a running application, we need to start our web server: @@ -261,32 +266,39 @@ Since Protractor works by interacting with a running application, we need to sta npm start ``` -Then in a separate terminal/command line window, we can run the Protractor test scripts against the -application by running: +Then, in a _separate_ terminal/command line window, we can run the Protractor test scripts against +the application by running: ``` npm run protractor ``` -Protractor will read the configuration file at `test/protractor-conf.js`. This configuration tells -Protractor to: +Protractor will read the configuration file at `e2e-tests/protractor-conf.js`. This configuration +file tells Protractor to: -- open up a Chrome browser and connect it to the application -- execute all the End to End tests in this browser -- report the results of these tests in the terminal/command line window -- close down the browser and exit +* Open up a Chrome browser and connect it to the application. +* Execute all the E2E tests in this browser. +* Report the results of these tests in the terminal/command line window. +* Close the browser and exit. -It is good to run the end to end tests whenever you make changes to the HTML views or want to check -that the application as a whole is executing correctly. It is very common to run End to End tests -before pushing a new commit of changes to a remote repository. +It is good to run the E2E tests whenever you make changes to the HTML views or want to check that +the application as a whole is executing correctly. It is very common to run E2E tests before pushing +a new commit of changes to a remote repository. + + +Now that you have set up your local machine, let's get started with the tutorial: +{@link step_00 Step 0 - Bootstrapping} -Now that you have set up your local machine, let's get started with the tutorial: {@link step_00 Step 0 - Bootstrapping} -[git]: http://git-scm.com/ -[node]: http://nodejs.org/ [angular-phonecat]: https://github.com/angular/angular-phonecat -[protractor]: https://github.com/angular/protractor [bower]: http://bower.io/ +[git]: http://git-scm.com/ [http-server]: https://github.com/nodeapps/http-server -[karma]: https://github.com/karma-runner/karma -[java]: https://www.java.com/en/download/help/download_options.xml +[jdk]: https://en.wikipedia.org/wiki/Java_Development_Kit +[jdk-download]: http://www.oracle.com/technetwork/java/javase/downloads/index.html +[karma]: https://karma-runner.github.io/ +[node]: http://nodejs.org/ +[nvm]: https://github.com/creationix/nvm +[nvm-windows]: https://github.com/coreybutler/nvm-windows +[protractor]: https://github.com/angular/protractor +[selenium]: http://docs.seleniumhq.org/ diff --git a/docs/content/tutorial/step_00.ngdoc b/docs/content/tutorial/step_00.ngdoc index 1a83fdf5ed2a..a9caee6369d5 100644 --- a/docs/content/tutorial/step_00.ngdoc +++ b/docs/content/tutorial/step_00.ngdoc @@ -7,11 +7,12 @@ In this step of the tutorial, you will become familiar with the most important source code files of -the AngularJS phonecat app. You will also learn how to start the development servers bundled with -angular-seed, and run the application in the browser. +the AngularJS Phonecat App. You will also learn how to start the development servers bundled with +[angular-seed][angular-seed], and run the application in the browser. -Before you continue, make sure you have set up your development environment and installed all necessary -dependencies, as described in {@link index#get-started Get Started}. +Before you continue, make sure you have set up your development environment and installed all +necessary dependencies, as described in the {@link tutorial/#environment-setup Environment Setup} +section. In the `angular-phonecat` directory, run this command: @@ -19,118 +20,130 @@ In the `angular-phonecat` directory, run this command: git checkout -f step-0 ``` - This resets your workspace to step 0 of the tutorial app. You must repeat this for every future step in the tutorial and change the number to the number of the step you are on. This will cause any changes you made within your working directory to be lost. -If you haven't already done so you need to install the dependencies by running: +If you haven't already done so, you need to install the dependencies by running: ``` npm install ``` -To see the app running in a browser, open a *separate* terminal/command line tab or window, then -run `npm start` to start the web server. Now, open a browser window for the app and navigate to -`http://localhost:8000/app/` +To see the app running in a browser, open a _separate_ terminal/command line tab or window, then run +`npm start` to start the web server. Now, open a browser window for the app and navigate to +http://localhost:8000/index.html. -Note that if you already ran the master branch app prior to checking out step-0, you may see the cached -master version of the app in your browser window at this point. Just hit refresh to re-load the page. +Note that if you already ran the master branch app prior to checking out step-0, you may see the +cached master version of the app in your browser window at this point. Just hit refresh to re-load +the page. You can now see the page in your browser. It's not very exciting, but that's OK. The HTML page that displays "Nothing here yet!" was constructed with the HTML code shown below. The code contains some key Angular elements that we will need as we progress. -__`app/index.html`:__ +**`app/index.html`:** ```html - - - - My HTML File - - - - - - -

Nothing here {{'yet' + '!'}}

- - + + + + My HTML File + + + + + +

Nothing here {{'yet' + '!'}}

+ + ``` - ## What is the code doing? -**`ng-app` directive:** +
+**`ng-app` attribute:** + +```html + +``` - +The `ng-app` attribute represents an Angular directive, named `ngApp` (Angular uses `kebab-case` for +its custom attributes and `camelCase` for the corresponding directives which implement them). This +directive is used to flag the HTML element that Angular should consider to be the root element of +our application. This gives application developers the freedom to tell Angular if the entire HTML +page or only a portion of it should be treated as the AngularJS application. - The `ng-app` attribute represents an Angular directive named `ngApp` (Angular uses - `spinal-case` for its custom attributes and `camelCase` for the corresponding directives - which implement them). - This directive is used to flag the html element that Angular should consider to be the root element - of our application. - This gives application developers the freedom to tell Angular if the entire html page or only a - portion of it should be treated as the Angular application. +For more info on `ngApp`, check out the {@link ng.directive:ngApp API Reference}. -**AngularJS script tag:** +
+**`angular.js` script tag:** - - + - +
Since Protractor works by interacting with a running application, we need to start our web server: diff --git a/docs/content/tutorial/step_00.ngdoc b/docs/content/tutorial/step_00.ngdoc index 965cfb4818fa..392251effd4c 100644 --- a/docs/content/tutorial/step_00.ngdoc +++ b/docs/content/tutorial/step_00.ngdoc @@ -79,7 +79,7 @@ directive is used to flag the HTML element that Angular should consider to be th our application. This gives application developers the freedom to tell Angular if the entire HTML page or only a portion of it should be treated as the AngularJS application. -For more info on `ngApp`, check out the {@link ng.directive:ngApp API Reference}. +For more info on `ngApp`, check out the {@link ngApp API Reference}.
**`angular.js` script tag:** @@ -90,9 +90,9 @@ For more info on `ngApp`, check out the {@link ng.directive:ngApp API Reference} This code downloads the `angular.js` script which registers a callback that will be executed by the browser when the containing HTML page is fully downloaded. When the callback is executed, Angular -looks for the {@link ng.directive:ngApp ngApp} directive. If Angular finds the directive, it will -bootstrap the application with the root of the application DOM being the element on which the -`ngApp` directive was defined. +looks for the {@link ngApp ngApp} directive. If Angular finds the directive, it will bootstrap the +application with the root of the application DOM being the element on which the `ngApp` directive +was defined. For more info on bootstrapping your app, checkout the [Bootstrap](guide/bootstrap) section of the Developer Guide. diff --git a/docs/content/tutorial/step_02.ngdoc b/docs/content/tutorial/step_02.ngdoc index 9eaabbe19530..ea62b1b935fb 100644 --- a/docs/content/tutorial/step_02.ngdoc +++ b/docs/content/tutorial/step_02.ngdoc @@ -50,8 +50,8 @@ The view is constructed by Angular from this template. ``` -We replaced the hard-coded phone list with the {@link ng.directive:ngRepeat ngRepeat} directive and -two {@link guide/expression Angular expressions}: +We replaced the hard-coded phone list with the {@link ngRepeat ngRepeat} directive and two +{@link guide/expression Angular expressions}: * The `ng-repeat="phone in phones"` attribute on the `
  • ` tag is an Angular repeater directive. The repeater tells Angular to create a `
  • ` element for each phone in the list, using the `
  • ` @@ -59,8 +59,8 @@ two {@link guide/expression Angular expressions}: * The expressions wrapped in curly braces (`{{phone.name}}` and `{{phone.snippet}}`) will be replaced by the values of the expressions. -We have also added a new directive, called {@link ng.directive:ngController ngController}, which -attaches a `PhoneListController` **controller** to the `` tag. At this point: +We have also added a new directive, called {@link ngController ngController}, which attaches a +`PhoneListController` **controller** to the `` tag. At this point: * `PhoneListController` is in charge of the DOM sub-tree under (and including) the `` element. * The expressions in curly braces (`{{phone.name}}` and `{{phone.snippet}}`) denote bindings, which @@ -112,9 +112,8 @@ Although the controller is not yet doing very much, it plays a crucial role. By for our data model, the controller allows us to establish data-binding between the model and the view. We connected the dots between the presentation, data, and logic components as follows: -* The {@link ng.directive:ngController ngController} directive, located on the `` tag, - references the name of our controller, `PhoneListController` (located in the JavaScript file - `app.js`). +* The {@link ngController ngController} directive, located on the `` tag, references the name + of our controller, `PhoneListController` (located in the JavaScript file `app.js`). * The `PhoneListController` controller attaches the phone data to the `$scope` that was injected into our controller function. This _scope_ is a prototypal descendant of the _root scope_ that was diff --git a/docs/content/tutorial/step_03.ngdoc b/docs/content/tutorial/step_03.ngdoc index 76bbd52448fd..6720561b71a4 100644 --- a/docs/content/tutorial/step_03.ngdoc +++ b/docs/content/tutorial/step_03.ngdoc @@ -64,8 +64,9 @@ application or vice versa.

  • -To create a component, we use the `.component()` method of an {@link module Angular module}. We must -provide the name of the component and the Component Definition Object (CDO for short). +To create a component, we use the {@link angular.Module#component .component()} method of an +{@link module Angular module}. We must provide the name of the component and the Component +Definition Object (CDO for short). Remember that (since components are also directives) the name of the component is in `camelCase`, but we will use `kebab-case`, when referring to it in our HTML. @@ -100,8 +101,7 @@ inside the controller constructor), instead of directly to the scope. From the template, we can refer to our controller instance using an alias. This way, the context of evaluation for our expressions is even more clear. By default, components use `$ctrl` as the -controller alias, but we can override it, should the need arise. (It is a very uncommon need though, -so we will be sticking with `$ctrl` most of the time.) +controller alias, but we can override it, should the need arise. There are more options available, so make sure you check out the {@link ng.$compileProvider#component API Reference}, before using `.component()` in your own @@ -223,7 +223,7 @@ describe('phoneList', function() { describe('PhoneListController', function() { it('should create a `phones` model with 3 phones', inject(function($componentController) { - var ctrl = $componentController('phoneList', {$scope: {}}); + var ctrl = $componentController('phoneList'); expect(ctrl.phones.length).toBe(3); })); diff --git a/docs/content/tutorial/step_04.ngdoc b/docs/content/tutorial/step_04.ngdoc index 643a8dd5061a..cc2e152f0b4a 100644 --- a/docs/content/tutorial/step_04.ngdoc +++ b/docs/content/tutorial/step_04.ngdoc @@ -53,7 +53,7 @@ We will keep this in mind though, as we add more features. So, now that we learned we should put everything in its own file, our `app/` directory will soon be full with dozens of files and specs (remember we keep our unit test files next to the corresponding -source code files). What's more important, logically related files will not be groupped together; it +source code files). What's more important, logically related files will not be grouped together; it will be really difficult of locate all files related to a specific section of the application and make a change or fix a bug. @@ -66,8 +66,8 @@ parts of the application. We will put those inside `app/core/`.

    - Other typical names for our `core` directory are `common` and `components`. The latter is kind - of misleading though, as it will contain other things than components as well. + Other typical names for our `core` directory are `shared`, `common` and `components`. The last + one is kind of misleading though, as it will contain other things than components as well.

    (This is mostly a relic of the past, when "components" just meant the generic building blocks of @@ -90,7 +90,7 @@ Based on what we have discussed so far, here is our directory/file layout for th ## Using Modules As previously mentioned, one of the benefits of having a modular architecture is code reuse — -not only inside the same application, but across application too. There is one final step in making +not only inside the same application, but across applications too. There is one final step in making this code reuse frictionless: * Each feature/section should declare its own module and all related entities should register @@ -175,11 +175,16 @@ will make all entities registered on `phoneList` available on `phonecatApp` as w we have created. This might seem tedious, but is totally worth it.

    - In a production-ready application, you are better off concatenating and minifying all your - JavaScript files anyway (for performance reasons), so this won't be an issue any more. + In a production-ready application, you would concatenate and minify all your JavaScript files + anyway (for performance reasons), so this won't be an issue any more.

    +
    + Note that files defining a module (i.e. `.module.js`) need to be included before other files that + add features (e.g. components, controllers, services, filters) to that module. +
    + ## External Templates @@ -193,7 +198,7 @@ IDE/editor has to offer (e.g. HTML-specific color-highlighting and auto-completi our component definitions cleaner. So, while it's perfectly fine to keep our component templates inline (using the `template` property -of the CDO), we decided to use an external template for our `phoneList` component. In order to +of the CDO), we are going to use an external template for our `phoneList` component. In order to denote that we are using an external template, we use the `templateUrl` property and specify the URL that our template will be loaded from. Since we want to keep our template close to where the component is defined, we place it inside `app/phone-list/`. @@ -242,7 +247,7 @@ HTTP request to get the template from `app/phone-list/phone-list.template.html`. ## Final Directory/File Layout -After all the refactorings that took place, this is how our application looks like from the outside: +After all the refactorings that took place, this is how our application looks from the outside:
    **`/`:** @@ -289,10 +294,10 @@ If not already done so, run the tests (using the `npm test` command) and verify pass.
    - One of the great things about tests is the confidence the provide, when refactoring your + One of the great things about tests is the confidence they provide, when refactoring your application. It's easy to break something as you start moving files around and re-arranging - modules. Having a good test coverage is the quickest, easiest and most reliable way of knowing - that your application will continue to work as expected. + modules. Having good test coverage is the quickest, easiest and most reliable way of knowing that + your application will continue to work as expected.
    diff --git a/docs/content/tutorial/step_05.ngdoc b/docs/content/tutorial/step_05.ngdoc index bd898dd4e0c9..e38e68e4e3f7 100644 --- a/docs/content/tutorial/step_05.ngdoc +++ b/docs/content/tutorial/step_05.ngdoc @@ -52,13 +52,12 @@ We made no changes to the component's controller. ``` -We added a standard HTML `` tag and used Angular's -{@link ng.filter:filter filter} function to process the input for the -{@link ng.directive:ngRepeat ngRepeat} directive. +We added a standard HTML `` tag and used Angular's {@link ng.filter:filter filter} function +to process the input for the {@link ngRepeat ngRepeat} directive. -By virtue of the {@link ng.directive:ngModel ngModel} directive, this lets a user enter search -criteria and immediately see the effects of their search on the phone list. This new code -demonstrates the following: +By virtue of the {@link ngModel ngModel} directive, this lets a user enter search criteria and +immediately see the effects of their search on the phone list. This new code demonstrates the +following: * Data-binding: This is one of the core features in Angular. When the page loads, Angular binds the value of the input box to the data model variable specified with `ngModel` and keeps the two in @@ -83,8 +82,8 @@ demonstrates the following: In previous steps, we learned how to write and run unit tests. Unit tests are perfect for testing controllers and other parts of our application written in JavaScript, but they can't easily -test DOM manipulation or the wiring of our application. For these, an end-to-end (E2E) test is a -much better choice. +test templates, DOM manipulation or interoperability of components and services. For these, an +end-to-end (E2E) test is a much better choice. The search feature was fully implemented via templates and data-binding, so we'll write our first E2E test, to verify that the feature works. @@ -132,13 +131,14 @@ Jasmine, the E2E test uses APIs of [Protractor][protractor]. Read about the Prot [Protractor API Docs][protractor-docs]. Much like Karma is the test runner for unit tests, we use Protractor to run E2E tests. Try it with -`npm run protractor`. E2E tests are slow, so unlike with unit tests, Protractor will exit after the +`npm run protractor`. E2E tests take time, so unlike with unit tests, Protractor will exit after the tests run and will not automatically rerun the test suite on every file change. To rerun the test suite, execute `npm run protractor` again.
    - **Note:** You must ensure your application is being served via a web server to test with - protractor. You can do this by using `npm start`. + **Note:** In order for protractor to access and run tests against your application, it must be + served via a web server. In a different terminal/command line window, run `npm start` to fire up + the web server.
    diff --git a/docs/content/tutorial/step_06.ngdoc b/docs/content/tutorial/step_06.ngdoc index 9165b17d20ce..d585ada05234 100644 --- a/docs/content/tutorial/step_06.ngdoc +++ b/docs/content/tutorial/step_06.ngdoc @@ -64,9 +64,9 @@ We made the following changes to the `phone-list.template.html` template: -* We then chained the `filter` filter with the {@link ng.filter:orderBy orderBy} filter to further - process the input for the repeater. `orderBy` is a filter that takes an input array, copies it and - reorders the copy which is then returned. +* We then chained the `filter` filter with the {@link orderBy orderBy} filter to further process the + input for the repeater. `orderBy` is a filter that takes an input array, copies it and reorders + the copy which is then returned. Angular creates a two way data-binding between the select element and the `$ctrl.orderProp` model. `$ctrl.orderProp` is then used as the input for the `orderBy` filter. @@ -143,7 +143,7 @@ describe('phoneList', function() { var ctrl; beforeEach(inject(function($componentController) { - ctrl = $componentController('phoneList', {$scope: {}}); + ctrl = $componentController('phoneList'); })); it('should create a `phones` model with 3 phones', function() { @@ -183,8 +183,10 @@ Let's turn our attention to the E2E tests. ... it('should be possible to control phone order via the drop-down menu', function() { + var queryField = element(by.model('$ctrl.query')); + var orderSelect = element(by.model('$ctrl.orderProp')); + var nameOption = orderSelect.element(by.css('option[value="name"]')); var phoneNameColumn = element.all(by.repeater('phone in $ctrl.phones').column('phone.name')); - var query = element(by.model('$ctrl.query')); function getNames() { return phoneNameColumn.map(function(elem) { @@ -192,14 +194,14 @@ Let's turn our attention to the E2E tests. }); } - query.sendKeys('tablet'); // Let's narrow the dataset to make the test assertions shorter + queryField.sendKeys('tablet'); // Let's narrow the dataset to make the assertions shorter expect(getNames()).toEqual([ 'Motorola XOOM\u2122 with Wi-Fi', 'MOTOROLA XOOM\u2122' ]); - element(by.model('$ctrl.orderProp')).element(by.css('option[value="name"]')).click(); + nameOption.click(); expect(getNames()).toEqual([ 'MOTOROLA XOOM\u2122', diff --git a/docs/content/tutorial/step_07.ngdoc b/docs/content/tutorial/step_07.ngdoc index 8b04c4cf2000..29f462456e1f 100644 --- a/docs/content/tutorial/step_07.ngdoc +++ b/docs/content/tutorial/step_07.ngdoc @@ -77,10 +77,10 @@ in this tutorial.) The `$http` service returns a {@link ng.$q promise object}, which has a `then()` method. We call this method to handle the asynchronous response and assign the phone data to the controller, as a -model called `phones`. Notice that Angular detected the JSON response and parsed it for us into the -`data` property of the `response` object passed to our callback! +property called `phones`. Notice that Angular detected the JSON response and parsed it for us into +the `data` property of the `response` object passed to our callback! -Since we are making the assignment of the `phones` model in a callback function, where the `this` +Since we are making the assignment of the `phones` property in a callback function, where the `this` value is not defined, we also introduce a local variable called `self` that points back to the controller instance. @@ -207,7 +207,7 @@ describe('phoneList', function() { $httpBackend.expectGET('phones/phones.json') .respond([{name: 'Nexus S'}, {name: 'Motorola DROID'}]); - ctrl = $componentController('phoneList', {$scope: {}}); + ctrl = $componentController('phoneList'); })); ... @@ -242,17 +242,18 @@ request from the controller. To do this we: {@link ngMock.$httpBackend mock version} of the service that in a production environment facilitates all XHR and JSONP requests. The mock version of this service allows us to write tests without having to deal with native APIs and the global state associated with them — both of which - make testing a nightmare. + make testing a nightmare. It also overcomes the asynchronous nature of these calls, which would + slow down unit tests. * Use the `$httpBackend.expectGET()` method to train the `$httpBackend` service to expect an incoming HTTP request and tell it what to respond with. Note that the responses are not returned until we call the `$httpBackend.flush()` method. -Now we will make assertions to verify that the `phones` model doesn't exist on the controller before -the response is received: +Now we will make assertions to verify that the `phones` property doesn't exist on the controller +before the response is received: ```js - it('should create a `phones` model with 2 phones fetched with `$http`', function() { + it('should create a `phones` property with 2 phones fetched with `$http`', function() { expect(ctrl.phones).toBeUndefined(); $httpBackend.flush(); @@ -265,12 +266,12 @@ the response is received: {@link ngMock.$httpBackend#flushing-http-requests Flushing HTTP requests} in the mock `$httpBackend` documentation for a full explanation of why this is necessary. -* We make the assertions, verifying that the `phones` model now exists on the controller. +* We make the assertions, verifying that the `phones` property now exists on the controller. Finally, we verify that the default value of `orderProp` is set correctly: ```js - it('should set a default value for the `orderProp` model', function() { + it('should set a default value for the `orderProp` property', function() { expect(ctrl.orderProp).toBe('age'); }); ``` diff --git a/docs/content/tutorial/step_08.ngdoc b/docs/content/tutorial/step_08.ngdoc index 1c69e97bd02c..0110b81861c9 100644 --- a/docs/content/tutorial/step_08.ngdoc +++ b/docs/content/tutorial/step_08.ngdoc @@ -62,12 +62,12 @@ now-familiar double-curly brace binding in the `href` attribute values. In step `{{phone.name}}` binding as the element content. In this step the `{{phone.id}}` binding is used in the element attribute. -We also added phone images next to each record using an image tag with the -{@link ng.directive:ngSrc ngSrc} directive. That directive prevents the browser from treating the -Angular `{{ expression }}` markup literally, and initiating a request to an invalid URL -(`http://localhost:8000/{{phone.imageUrl}}`), which it would have done if we had only specified an -attribute binding in a regular `src` attribute (``). Using the `ngSrc` -directive, prevents the browser from making an HTTP request to an invalid location. +We also added phone images next to each record using an image tag with the {@link ngSrc ngSrc} +directive. That directive prevents the browser from treating the Angular `{{ expression }}` markup +literally, and initiating a request to an invalid URL (`http://localhost:8000/{{phone.imageUrl}}`), +which it would have done if we had only specified an attribute binding in a regular `src` attribute +(``). Using the `ngSrc` directive, prevents the browser from making an +HTTP request to an invalid location. # Testing @@ -83,9 +83,7 @@ directive, prevents the browser from making an HTTP request to an invalid locati query.sendKeys('nexus'); element.all(by.css('.phones li a')).first().click(); - browser.getLocationAbsUrl().then(function(url) { - expect(url).toBe('/phones/nexus-s'); - }); + expect(browser.getLocationAbsUrl()).toBe('/phones/nexus-s'); }); ... diff --git a/docs/content/tutorial/step_09.ngdoc b/docs/content/tutorial/step_09.ngdoc index 0f0206674500..bdf19d3ce706 100644 --- a/docs/content/tutorial/step_09.ngdoc +++ b/docs/content/tutorial/step_09.ngdoc @@ -114,8 +114,8 @@ The injector only carries out the following steps: * Load the module definition(s) that you specify in your application. * Register all Providers defined in these module definition(s). -* When asked to do so, inject a specified function and any necessary dependencies (services), that - it lazily instantiates via their Providers. +* When asked to do so, lazily instantiate services and their dependencies, via their Providers, as + parameters to an injectable function. Providers are objects that provide (create) instances of services and expose configuration APIs, that can be used to control the creation and runtime behavior of a service. In case of the `$route` @@ -126,9 +126,9 @@ service, the `$routeProvider` exposes APIs that allow you to define routes for y `$routeProvider` into `PhoneListController` at runtime. -Angular modules solve the problem of removing global state from the application and provide a way -of configuring the injector. As opposed to AMD or require.js modules, Angular modules don't try to -solve the problem of script load ordering or lazy script fetching. These goals are totally +Angular modules solve the problem of removing global variables from the application and provide a +way of configuring the injector. As opposed to AMD or require.js modules, Angular modules don't try +to solve the problem of script load ordering or lazy script fetching. These goals are totally independent and both module systems can live side-by-side and fulfill their goals. To deepen your understanding on Angular's DI, see [Understanding Dependency Injection][wiki-di]. @@ -330,7 +330,7 @@ any modification. ```js files: [ 'bower_components/angular/angular.js', - 'bower_components/angular-resource/angular-resource.js', + 'bower_components/angular-route/angular-route.js', ... ], ``` @@ -347,9 +347,7 @@ various URLs and verifying that the correct view was rendered. it('should redirect `index.html` to `index.html#/phones', function() { browser.get('index.html'); - browser.getLocationAbsUrl().then(function(url) { - expect(url).toBe('/phones'); - }); + expect(browser.getLocationAbsUrl()).toBe('/phones'); }); ... diff --git a/docs/content/tutorial/step_10.ngdoc b/docs/content/tutorial/step_10.ngdoc index 4ba5a6d3581c..22470ceeebcd 100644 --- a/docs/content/tutorial/step_10.ngdoc +++ b/docs/content/tutorial/step_10.ngdoc @@ -146,7 +146,7 @@ describe('phoneDetail', function() { $routeParams.phoneId = 'xyz'; - ctrl = $componentController('phoneDetail', {$scope: {}}); + ctrl = $componentController('phoneDetail'); })); it('should fetch the phone details', function() { diff --git a/docs/content/tutorial/step_14.ngdoc b/docs/content/tutorial/step_14.ngdoc index 77a7b247a46a..f004eb988534 100644 --- a/docs/content/tutorial/step_14.ngdoc +++ b/docs/content/tutorial/step_14.ngdoc @@ -12,9 +12,8 @@ the template code we created earlier. * We now use the {@link ngAnimate ngAnimate} module to enable animations throughout the application. * We also rely on built-in directives to automatically trigger hooks for animations to tap into. * When an animation is found, it will run along with the actual DOM operation that is being issued - on the element at the given time (e.g. inserting/removing nodes on - {@link ng.directive:ngRepeat ngRepeat} or adding/removing classes on - {@link ng.directive:ngClass ngClass}). + on the element at the given time (e.g. inserting/removing nodes on {@link ngRepeat ngRepeat} or + adding/removing classes on {@link ngClass ngClass}).
    @@ -367,7 +366,7 @@ Just like with the thumbnails, we are using a repeater to display **all** the pr list, however we're not animating any repeat-related transitions. Instead, we will be keeping our eye on each element's classes and especially the `selected` class, since its presence or absence will determine if the element is visible or hidden. The addition/removal of the `selected` class is -managed by the {@link ng.directive:ngClass ngClass} directive, based on the specified condition +managed by the {@link ngClass ngClass} directive, based on the specified condition (`img === $ctrl.mainImageUrl`). In our case, there is always exactly one element that has the `selected` class, and therefore there will be exactly one phone profile image visible on the screen at all times. From 26d3abe2201cdea30fce65666d887165ad324410 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Thu, 19 May 2016 22:39:09 +0300 Subject: [PATCH 4/6] fixup 2 - Fix typos. - Fix navigation for steps > 12. - Make section title consistent (include "Component" where appropriate). - Improve alert formatting (titles, line spacing). --- docs/app/src/tutorials.js | 7 +++--- docs/config/templates/indexPage.template.html | 8 +++---- docs/content/tutorial/index.ngdoc | 23 +++++++++++++++---- docs/content/tutorial/step_00.ngdoc | 2 +- docs/content/tutorial/step_02.ngdoc | 2 +- docs/content/tutorial/step_03.ngdoc | 11 +++++---- docs/content/tutorial/step_05.ngdoc | 6 +++++ docs/content/tutorial/step_06.ngdoc | 4 ++-- docs/content/tutorial/step_07.ngdoc | 4 ++-- docs/content/tutorial/step_08.ngdoc | 2 +- docs/content/tutorial/step_09.ngdoc | 4 ++++ docs/content/tutorial/step_10.ngdoc | 4 ++-- docs/content/tutorial/step_11.ngdoc | 2 +- docs/content/tutorial/step_12.ngdoc | 4 ++-- docs/content/tutorial/step_13.ngdoc | 2 +- 15 files changed, 56 insertions(+), 29 deletions(-) diff --git a/docs/app/src/tutorials.js b/docs/app/src/tutorials.js index 84ea6171a743..09df4138fc96 100644 --- a/docs/app/src/tutorials.js +++ b/docs/app/src/tutorials.js @@ -5,7 +5,8 @@ angular.module('tutorials', []) '', 'step_00', 'step_01', 'step_02', 'step_03', 'step_04', 'step_05', 'step_06', 'step_07', 'step_08', 'step_09', - 'step_10', 'step_11', 'step_12', 'the_end' + 'step_10', 'step_11', 'step_12', 'step_13', 'step_14', + 'the_end' ]; return { scope: {}, @@ -43,7 +44,7 @@ angular.module('tutorials', []) '
    Step {{step}} Live Demo.

    \n' + '\n' + '

    The most important changes are listed below. You can see the full diff on ' + - 'GitHub\n' + + 'GitHub.\n' + '

    ' }; -}); \ No newline at end of file +}); diff --git a/docs/config/templates/indexPage.template.html b/docs/config/templates/indexPage.template.html index 82a75fba00fe..cbdbc2fadebe 100644 --- a/docs/config/templates/indexPage.template.html +++ b/docs/config/templates/indexPage.template.html @@ -228,10 +228,10 @@

    {{ key }}

    )

    - Code licensed under the - The - MIT License. Documentation licensed under CC BY 3.0. + Code licensed under + The MIT License. + Documentation licensed under + CC BY 3.0.

    diff --git a/docs/content/tutorial/index.ngdoc b/docs/content/tutorial/index.ngdoc index fa79da38c097..f7de34422974 100644 --- a/docs/content/tutorial/index.ngdoc +++ b/docs/content/tutorial/index.ngdoc @@ -97,6 +97,7 @@ The tutorial instructions, from now on, assume you are running all commands from `angular-phonecat` directory.
    +

    **Firewall/Proxy Issues?**

    `git` and other tools (for example `bower` - see below), often use the `git:` protocol for accessing files in remote repositories. Some firewall configurations are blocking `git://` URLs, @@ -266,11 +267,25 @@ npm run update-webdriver

    - Under the hood, Protractor uses the [Selenium Stadalone Server][selenium], which in turn requires - the [Java Development Kit (JDK)][jdk] to be installed on your local machine. Check this - by running `java -version` from the command line. +

    + Running `update-webdriver` for the first time may take from several seconds up to a few minutes + (depending on your hardware and network connection). If you cancel the operation (e.g. using + `Ctrl+C`), you might get errors, when trying to run Protractor later. +

    +

    + In that case, you can delete the `node_modules/` directory and run `npm install` again. +

    +
    - If JDK is not already installed, you can download it [here][jdk-download]. +
    +

    + Under the hood, Protractor uses the [Selenium Stadalone Server][selenium], which in turn + requires the [Java Development Kit (JDK)][jdk] to be installed on your local machine. Check this + by running `java -version` from the command line. +

    +

    + If JDK is not already installed, you can download it [here][jdk-download]. +

    Since Protractor works by interacting with a running application, we need to start our web server: diff --git a/docs/content/tutorial/step_00.ngdoc b/docs/content/tutorial/step_00.ngdoc index 392251effd4c..91d8bad361f7 100644 --- a/docs/content/tutorial/step_00.ngdoc +++ b/docs/content/tutorial/step_00.ngdoc @@ -85,7 +85,7 @@ For more info on `ngApp`, check out the {@link ngApp API Reference}. **`angular.js` script tag:** ```html - ``` This code downloads the `angular.js` script which registers a callback that will be executed by the diff --git a/docs/content/tutorial/step_02.ngdoc b/docs/content/tutorial/step_02.ngdoc index ea62b1b935fb..fc6eecdecf8a 100644 --- a/docs/content/tutorial/step_02.ngdoc +++ b/docs/content/tutorial/step_02.ngdoc @@ -206,7 +206,7 @@ describe('PhoneListController', function() { * With this instance, we verify that the phones array property on the scope contains three records.
    - **A note on file naming:** +

    **A note on file naming:**

    As already mentioned in the [introduction](tutorial/#running-unit-tests), the unit test files (specs) are kept side-by-side with the application code. We name our specs after the file diff --git a/docs/content/tutorial/step_03.ngdoc b/docs/content/tutorial/step_03.ngdoc index 6720561b71a4..7d9e3665a466 100644 --- a/docs/content/tutorial/step_03.ngdoc +++ b/docs/content/tutorial/step_03.ngdoc @@ -187,11 +187,12 @@ Voilà! The resulting output should look the same, but let's see what we have ga

    - **A note on file naming:** -
    - It is a good practice to distinguish different types of entities by suffix. In this tutorial, we - are using the `.component` suffix for components, so the definition of a `someComponent` component - would be in a file named `some-component.component.js`. +

    **A note on file naming:**

    +

    + It is a good practice to distinguish different types of entities by suffix. In this tutorial, we + are using the `.component` suffix for components, so the definition of a `someComponent` + component would be in a file named `some-component.component.js`. +

    diff --git a/docs/content/tutorial/step_05.ngdoc b/docs/content/tutorial/step_05.ngdoc index e38e68e4e3f7..f18405ec5d88 100644 --- a/docs/content/tutorial/step_05.ngdoc +++ b/docs/content/tutorial/step_05.ngdoc @@ -141,6 +141,12 @@ To rerun the test suite, execute `npm run protractor` again. the web server.
    +
    + The web server is configured to use port 8000. If the port is already in use (for example by + another instance of a running web server) you will get an `EADDRINUSE` error. Make sure the port + is available before running `npm start`. +
    + # Experiments diff --git a/docs/content/tutorial/step_06.ngdoc b/docs/content/tutorial/step_06.ngdoc index d585ada05234..239d413ecf33 100644 --- a/docs/content/tutorial/step_06.ngdoc +++ b/docs/content/tutorial/step_06.ngdoc @@ -17,7 +17,7 @@ the repeater, and letting the data binding magic do the rest of the work.
    -## Template +## Component Template
    **`app/phone-list/phone-list.template.html`:** @@ -77,7 +77,7 @@ menu), Angular's data-binding will cause the view to automatically update. No bl manipulation code is necessary! -## Controller +## Component Controller
    **`app/phone-list/phone-list.components.js`:** diff --git a/docs/content/tutorial/step_07.ngdoc b/docs/content/tutorial/step_07.ngdoc index 29f462456e1f..0fb439bb2768 100644 --- a/docs/content/tutorial/step_07.ngdoc +++ b/docs/content/tutorial/step_07.ngdoc @@ -38,7 +38,7 @@ Following is a sample of the file: ``` -## Controller +## Component Controller We will use Angular's {@link ng.$http $http} service in our controller for making an HTTP request to our web server to fetch the data in the `app/phones/phones.json` file. `$http` is just one of @@ -55,7 +55,7 @@ themselves, but by the DI subsystem). As a result, applications are easier to te ```js angular. - module('phoneList). + module('phoneList'). component('phoneList', { templateUrl: 'phone-list/phone-list.template.html', controller: function PhoneListController($http) { diff --git a/docs/content/tutorial/step_08.ngdoc b/docs/content/tutorial/step_08.ngdoc index 0110b81861c9..5f7a98efafea 100644 --- a/docs/content/tutorial/step_08.ngdoc +++ b/docs/content/tutorial/step_08.ngdoc @@ -38,7 +38,7 @@ URLs point to the `app/img/phones/` directory. ``` -## Template +## Component Template
    **`app/phone-list/phone-list.template.html`:** diff --git a/docs/content/tutorial/step_09.ngdoc b/docs/content/tutorial/step_09.ngdoc index bdf19d3ce706..63aa316658f1 100644 --- a/docs/content/tutorial/step_09.ngdoc +++ b/docs/content/tutorial/step_09.ngdoc @@ -358,6 +358,10 @@ various URLs and verifying that the correct view was rendered. browser.get('index.html#/phones'); }); + ... + + }); + ... describe('View: Phone details', function() { diff --git a/docs/content/tutorial/step_10.ngdoc b/docs/content/tutorial/step_10.ngdoc index 22470ceeebcd..79d8eae591de 100644 --- a/docs/content/tutorial/step_10.ngdoc +++ b/docs/content/tutorial/step_10.ngdoc @@ -52,7 +52,7 @@ Each of these files describes various properties of the phone using the same dat show this data in the phone details view. -## Controller +## Component Controller We will expand the `phoneDetail` component's controller by using the `$http` service to fetch the appropriate JSON files. This works the same way as the `phoneList` component's controller. @@ -81,7 +81,7 @@ To construct the URL for the HTTP request, we use `$routeParams.phoneId`, which the current route by the `$route` service. -## Template +## Component Template The inline, TBD placeholder template has been replaced with a full blown external template, including lists and bindings that comprise the phone details. Note how we use the Angular diff --git a/docs/content/tutorial/step_11.ngdoc b/docs/content/tutorial/step_11.ngdoc index c25f6e1cb968..d22809cb658a 100644 --- a/docs/content/tutorial/step_11.ngdoc +++ b/docs/content/tutorial/step_11.ngdoc @@ -66,7 +66,7 @@ angular.module('phonecatApp', [ ``` -## Template +## Templates Since we have created two new files (**core.module.js**, **checkmark.filter.js**), we need to include them in our layout template. diff --git a/docs/content/tutorial/step_12.ngdoc b/docs/content/tutorial/step_12.ngdoc index bc9937759b93..7902e14684f1 100644 --- a/docs/content/tutorial/step_12.ngdoc +++ b/docs/content/tutorial/step_12.ngdoc @@ -16,7 +16,7 @@ In this step, you will add a clickable phone image swapper to the phone details
    -## Controller +## Component Controller
    **`app/phone-detail/phone-detail.component.js`:** @@ -47,7 +47,7 @@ We also created a `setImage()` method (to be used as event handler), that will c `mainImageUrl`. -## Template +## Component Template
    **`app/phone-detail/phone-detail.template.html`:** diff --git a/docs/content/tutorial/step_13.ngdoc b/docs/content/tutorial/step_13.ngdoc index 4bafdd96a8ed..a15c75963d06 100644 --- a/docs/content/tutorial/step_13.ngdoc +++ b/docs/content/tutorial/step_13.ngdoc @@ -138,7 +138,7 @@ need to load the `angular-resource.js` file, which contains the `ngResource` mod ``` -## Controller +## Component Controllers We can now simplify our component controllers (`PhoneListController` and `PhoneDetailController`) by factoring out the lower-level `$http` service, replacing it with the new `Phone` service. Angular's From b555f2c8e152488c4bfa43f9f27119a4d1e2735f Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Sat, 21 May 2016 14:50:23 +0300 Subject: [PATCH 5/6] fixup 3 - Fix typos. - Improve common issues descriptions. - Move common setup issues to dedicated section. --- docs/content/tutorial/index.ngdoc | 85 +++++++++++++++-------------- docs/content/tutorial/step_05.ngdoc | 6 -- 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/docs/content/tutorial/index.ngdoc b/docs/content/tutorial/index.ngdoc index f7de34422974..e17cae45c61c 100644 --- a/docs/content/tutorial/index.ngdoc +++ b/docs/content/tutorial/index.ngdoc @@ -96,20 +96,6 @@ cd angular-phonecat The tutorial instructions, from now on, assume you are running all commands from within the `angular-phonecat` directory. -
    -

    **Firewall/Proxy Issues?**

    -

    - `git` and other tools (for example `bower` - see below), often use the `git:` protocol for - accessing files in remote repositories. Some firewall configurations are blocking `git://` URLs, - which leads to errors when trying to clone repositories or download dependencies. (For example - corporate firewalls are "notorious" for blocking `git:`.) -

    -

    - If you run into this issue, you can force the use of `https:` instead, by running the following - command: `git config --global url."https://".insteadOf git://` -

    -
    - ### Install Node.js @@ -213,7 +199,8 @@ You can now browse to the application at http://localhost:8000/index.html.
    To serve the web app on a different IP address or port, edit the "start" script within - `package.json`. You can use `-a` to set the address and `-p` to set the port. + `package.json`. You can use `-a` to set the address and `-p` to set the port. You also need to + update the `baseUrl` configuration property in `e2e-test/protractor.conf.js`.
    @@ -235,8 +222,8 @@ npm test This will start the Karma unit test runner. Karma will read the configuration file `karma.conf.js`, located at the root of the project directory. This configuration file tells Karma to: -* Open up a Chrome browser and connect it to Karma. -* Execute all the unit tests in this browser. +* Open up instances of the Chrome and Firefox browsers and connect them to Karma. +* Execute all the unit tests in these browsers. * Report the results of these tests in the terminal/command line window. * Watch all the project's JavaScript files and re-run the tests whenever any of these change. @@ -266,28 +253,6 @@ npm run update-webdriver automatically executed as part of the command that runs the E2E tests. -
    -

    - Running `update-webdriver` for the first time may take from several seconds up to a few minutes - (depending on your hardware and network connection). If you cancel the operation (e.g. using - `Ctrl+C`), you might get errors, when trying to run Protractor later. -

    -

    - In that case, you can delete the `node_modules/` directory and run `npm install` again. -

    -
    - -
    -

    - Under the hood, Protractor uses the [Selenium Stadalone Server][selenium], which in turn - requires the [Java Development Kit (JDK)][jdk] to be installed on your local machine. Check this - by running `java -version` from the command line. -

    -

    - If JDK is not already installed, you can download it [here][jdk-download]. -

    -
    - Since Protractor works by interacting with a running application, we need to start our web server: ``` @@ -301,7 +266,7 @@ the application by running: npm run protractor ``` -Protractor will read the configuration file at `e2e-tests/protractor-conf.js`. This configuration +Protractor will read the configuration file at `e2e-tests/protractor.conf.js`. This configuration file tells Protractor to: * Open up a Chrome browser and connect it to the application. @@ -314,6 +279,46 @@ the application as a whole is executing correctly. It is very common to run E2E a new commit of changes to a remote repository. +### Common Issues + +
    +**Firewall / Proxy issues** + +Git and other tools, often use the `git:` protocol for accessing files in remote repositories. +Some firewall configurations are blocking `git://` URLs, which leads to errors when trying to clone +repositories or download dependencies. (For example corporate firewalls are "notorious" for blocking +`git:`.) + +If you run into this issue, you can force the use of `https:` instead, by running the following +command: `git config --global url."https://".insteadOf git://` + +
    +**Updating WebDriver takes too long** + +Running `update-webdriver` for the first time may take from several seconds up to a few minutes +(depending on your hardware and network connection). If you cancel the operation (e.g. using +`Ctrl+C`), you might get errors, when trying to run Protractor later. + +In that case, you can delete the `node_modules/` directory and run `npm install` again. + +
    +**Protractor dependencies** + +Under the hood, Protractor uses the [Selenium Stadalone Server][selenium], which in turn requires +the [Java Development Kit (JDK)][jdk] to be installed on your local machine. Check this by running +`java -version` from the command line. + +If JDK is not already installed, you can download it [here][jdk-download]. + +
    +**Error running the web server** + +The web server is configured to use port 8000. If the port is already in use (for example by another +instance of a running web server) you will get an `EADDRINUSE` error. Make sure the port is +available, before running `npm start`. + +
    + Now that you have set up your local machine, let's get started with the tutorial: {@link step_00 Step 0 - Bootstrapping} diff --git a/docs/content/tutorial/step_05.ngdoc b/docs/content/tutorial/step_05.ngdoc index f18405ec5d88..e38e68e4e3f7 100644 --- a/docs/content/tutorial/step_05.ngdoc +++ b/docs/content/tutorial/step_05.ngdoc @@ -141,12 +141,6 @@ To rerun the test suite, execute `npm run protractor` again. the web server. -
    - The web server is configured to use port 8000. If the port is already in use (for example by - another instance of a running web server) you will get an `EADDRINUSE` error. Make sure the port - is available before running `npm start`. -
    - # Experiments From d7be60fbfd577c1954d348bb56c2455cef98ae4d Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Tue, 24 May 2016 00:00:32 +0300 Subject: [PATCH 6/6] fixup 4 - Use `!` as hash-prefix. --- docs/content/tutorial/step_09.ngdoc | 38 ++++++++++++++++++++--------- docs/content/tutorial/step_10.ngdoc | 2 +- docs/content/tutorial/step_14.ngdoc | 4 +-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/docs/content/tutorial/step_09.ngdoc b/docs/content/tutorial/step_09.ngdoc index 63aa316658f1..c0b0b304bf7d 100644 --- a/docs/content/tutorial/step_09.ngdoc +++ b/docs/content/tutorial/step_09.ngdoc @@ -9,7 +9,7 @@ In this step, you will learn how to create a layout template and how to build an application that has multiple views by adding routing, using an Angular module called {@link ngRoute ngRoute}. -* When you now navigate to `/index.html`, you are redirected to `/index.html#/phones` and the phone +* When you now navigate to `/index.html`, you are redirected to `/index.html#!/phones` and the phone list appears in the browser. * When you click on a phone link, the URL changes to that specific phone and the stub of a phone detail page is displayed. @@ -193,9 +193,9 @@ angular.module('phonecatApp', [ ]); ``` -Now we can configure the `$route` service (using it's provider) for our application. In order to be -able to quickly locate the configuration code, we put it into a separate file and used the `.config` -suffix. +Now, in addition to the core services and directives, we can also configure the `$route` service +(using it's provider) for our application. In order to be able to quickly locate the configuration +code, we put it into a separate file and used the `.config` suffix.
    **`app/app.config.js`:** @@ -203,8 +203,10 @@ suffix. ```js angular. module('phonecatApp'). - config(['$routeProvider', - function config($routeProvider) { + config(['$locationProvider', '$routeProvider', + function config($locationProvider, $routeProvider) { + $locationProvider.hashPrefix('!'); + $routeProvider. when('/phones', { template: '' @@ -217,11 +219,25 @@ suffix. ]); ``` -Using the `.config()` method, we request the `$routeProvider` to be injected into our configuration -function and use the {@link ngRoute.$routeProvider#when $routeProvider.when()} and +Using the `.config()` method, we request the necessary providers (for example the `$routeProvider`) +to be injected into our configuration function and then use their methods to specify the behavior of +the corresponding services. Here, we use the +{@link ngRoute.$routeProvider#when $routeProvider.when()} and {@link ngRoute.$routeProvider#otherwise $routeProvider.otherwise()} methods to define our application routes. +
    +

    + We also used {@ink $locationProvider#hashPrefix $locationProvider.hashPrefix()} to set the + hash-prefix to `!`. This prefix will appear in the links to our client-side routes, right after + the hash (`#`) symbol and before the actual path (e.g. `index.html#!/some/path`). +

    +

    + Setting a prefix is not necessary, but it is considered a good practice (for reasons that are + outside the scope of this tutorial). `!` is the most commonly used prefix. +

    +
    + Our routes are defined as follows: * `when('/phones')`: Determines the view that will be shown, when the URL hash fragment is @@ -345,7 +361,7 @@ various URLs and verifying that the correct view was rendered. ```js ... - it('should redirect `index.html` to `index.html#/phones', function() { + it('should redirect `index.html` to `index.html#!/phones', function() { browser.get('index.html'); expect(browser.getLocationAbsUrl()).toBe('/phones'); }); @@ -355,7 +371,7 @@ various URLs and verifying that the correct view was rendered. describe('View: Phone list', function() { beforeEach(function() { - browser.get('index.html#/phones'); + browser.get('index.html#!/phones'); }); ... @@ -367,7 +383,7 @@ various URLs and verifying that the correct view was rendered. describe('View: Phone details', function() { beforeEach(function() { - browser.get('index.html#/phones/nexus-s'); + browser.get('index.html#!/phones/nexus-s'); }); it('should display placeholder page with `phoneId`', function() { diff --git a/docs/content/tutorial/step_10.ngdoc b/docs/content/tutorial/step_10.ngdoc index 79d8eae591de..0305c80f80be 100644 --- a/docs/content/tutorial/step_10.ngdoc +++ b/docs/content/tutorial/step_10.ngdoc @@ -179,7 +179,7 @@ heading on the page is "Nexus S". describe('View: Phone detail', function() { beforeEach(function() { - browser.get('index.html#/phones/nexus-s'); + browser.get('index.html#!/phones/nexus-s'); }); it('should display the `nexus-s` page', function() { diff --git a/docs/content/tutorial/step_14.ngdoc b/docs/content/tutorial/step_14.ngdoc index f004eb988534..378b6f0ffbfe 100644 --- a/docs/content/tutorial/step_14.ngdoc +++ b/docs/content/tutorial/step_14.ngdoc @@ -157,10 +157,10 @@ order to be able to hook into it with our CSS animation code.