483 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			483 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
include ../../../_includes/_util-fns
 | 
						|
 | 
						|
:marked
 | 
						|
  Let's start from zero and build a super simple Angular 2 application in JavaScript.
 | 
						|
 | 
						|
.callout.is-helpful
 | 
						|
  header Don't want JavaScript?
 | 
						|
  :marked
 | 
						|
    Although we're getting started in JavaScript, you can also write Angular 2 apps
 | 
						|
    in TypeScript and Dart by selecting either of those languages from the combo-box in the banner.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## See It Run!
 | 
						|
 | 
						|
  Running the [live example](/resources/live-examples/quickstart/js/plnkr.html)
 | 
						|
  is the quickest way to see an Angular 2 app come to life.
 | 
						|
  
 | 
						|
  Clicking that link fires up a browser, loads the sample in [plunker](http://plnkr.co/ "Plunker"),
 | 
						|
  and displays a simple message:
 | 
						|
 | 
						|
figure.image-display
 | 
						|
  img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="Output of quickstart app")
 | 
						|
:marked
 | 
						|
  Here is the file structure:
 | 
						|
 | 
						|
code-example(format="").
 | 
						|
  angular2-quickstart
 | 
						|
  ├─ app
 | 
						|
  │   ├── app.component.js
 | 
						|
  │   └── boot.js
 | 
						|
  ├─ index.htm  
 | 
						|
  └─ license.md
 | 
						|
:marked
 | 
						|
  Functionally, it's an `index.html` and two JavaScript files in an `app/` folder.
 | 
						|
  We can handle that!
 | 
						|
  
 | 
						|
  Of course we won't build  many apps that only run in plunker. 
 | 
						|
  Let's follow a process that's closer to what we'd do in real life.
 | 
						|
  
 | 
						|
  1. Set up our development environment
 | 
						|
  1. Write the Angular root component for our app
 | 
						|
  1. Bootstrap it to take control of the main web page
 | 
						|
  1. Write the main page (`index.html`)
 | 
						|
  
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    We really can build the QuickStart from scratch in five minutes 
 | 
						|
    if we follow the instructions and ignore the commentary.
 | 
						|
    
 | 
						|
    Most of us will be interested in the "why" as well as the "how" and that will take longer.
 | 
						|
:marked
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Development Environment
 | 
						|
  
 | 
						|
  We'll need a place to stand (the application project folder), some libraries, 
 | 
						|
  some TypeScript configuration and the TypeScript-aware editor of your choice.
 | 
						|
 | 
						|
  ### Create a new project folder
 | 
						|
  
 | 
						|
code-example(format="").
 | 
						|
  mkdir angular2-quickstart
 | 
						|
  cd    angular2-quickstart
 | 
						|
:marked
 | 
						|
  ### Add the libraries we need
 | 
						|
  
 | 
						|
  We recommend the **npm** package manager for acquiring and managing our development libraries.
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    Don't have npm?
 | 
						|
    [Get it now](https://docs.npmjs.com/getting-started/installing-node "Installing Node.js and updating npm")
 | 
						|
    because we're going to use it now and repeatedly throughout this documentation.
 | 
						|
:marked
 | 
						|
  Add a **package.json** file to the project folder and copy/paste the following:
 | 
						|
+makeJson('quickstart/js/package.1.json', null, 'package.json')(format=".")  
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    Itching to know the details? We explain in the [appendix below](#package-json)  
 | 
						|
:marked
 | 
						|
  Install these packages by opening a terminal window (command window in Windows) and
 | 
						|
  running this npm command.
 | 
						|
code-example(format="").
 | 
						|
  npm install
 | 
						|
:marked
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    Scary <span style="color:red; font-weight: bold">error messages in red</span> may appear **during** install. 
 | 
						|
    Ignore them. The install will succeed. See the [appendix below](#npm-errors) for more information.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Our First Angular Component
 | 
						|
  
 | 
						|
  The *Component* is the most fundamental of Angular concepts. 
 | 
						|
  A component manages a view - a piece of the web page where we display information
 | 
						|
  to the user and respond to user feedback.
 | 
						|
  
 | 
						|
  Technically, a component is a class that controls a view template.
 | 
						|
  We'll write a lot of them as we build Angular apps. This is our first attempt
 | 
						|
  so we'll keep it ridiculously simple.
 | 
						|
  
 | 
						|
  ### Create an application source sub-folder
 | 
						|
  
 | 
						|
  We like to keep our application code in a sub-folder off the root called `app/`.
 | 
						|
  Execute the following command in the console window.
 | 
						|
code-example(format="").
 | 
						|
  mkdir app
 | 
						|
  cd    app
 | 
						|
:marked
 | 
						|
  ### Add the component file
 | 
						|
  Now add a file named **app.component.js** and paste the following lines:
 | 
						|
+makeExample('quickstart/js/app/app.component.js', null, 'app/app.component.js')(format=".")
 | 
						|
:marked
 | 
						|
  We're creating a visual component named **`AppComponent`** by chaining the
 | 
						|
  `Component` and `Class` methods that belong to the **global Angular core namespace, `ng.core`**.
 | 
						|
  
 | 
						|
+makeExample('quickstart/js/app/app.component.js', 'ng-namespace-funcs', 'app/component.js (Angular 2 methods)')(format=".")
 | 
						|
  
 | 
						|
:marked
 | 
						|
  The **`Component`** method takes a configuration object with two
 | 
						|
  properties. The **`Class`** method is where we implement the component itself,
 | 
						|
  giving it properties and methods that bind to the view and whatever
 | 
						|
  behavior is appropriate for this part of the UI.
 | 
						|
  
 | 
						|
  Let's review this file in detail.
 | 
						|
 | 
						|
  ### Modules
 | 
						|
  Angular apps are modular. They consist of many files each dedicated to a purpose.
 | 
						|
  ES5 JavaScript doesn't have modules, but we don't want to pollute the global namespace.
 | 
						|
  
 | 
						|
  So we'll surround the code in a simple IIFE ("Immediately Invoked Function Execution").
 | 
						|
  It receives our `app` 'namespace' object as argument. 
 | 
						|
  We call our IIFE with `window.app` if it exists - and if it doesn't we 
 | 
						|
  initialize it as an empty object.
 | 
						|
  
 | 
						|
+makeExample('quickstart/js/app/app.component.js', 'iife', 'app/component.js (IIFE)')(format=".")
 | 
						|
  
 | 
						|
:marked
 | 
						|
  Most application files *export* one thing into our faux-pas 'namespace', such as a component.
 | 
						|
  Our `app.component.js` file exports the `AppComponent`.
 | 
						|
  
 | 
						|
+makeExample('quickstart/js/app/app.component.js', 'export', 'app/component.js (export)')(format=".")
 | 
						|
  
 | 
						|
:marked
 | 
						|
  A more sophisticated application would have child components that descended from
 | 
						|
  `AppComponent` in a visual tree. 
 | 
						|
  A more sophisticated app would have more files and modules, at least as many as it had components.
 | 
						|
  
 | 
						|
  Quickstart isn't sophisticated; one component is all we need.
 | 
						|
  Yet modules play a fundamental organizational role in even this small app.
 | 
						|
  
 | 
						|
  Modules rely on other modules. In JavaScript Angular apps, when we need something
 | 
						|
  provided by another module, we get it from the `app` object. 
 | 
						|
  When another module needs to refer to `AppComponent`, it gets it from the `app.AppComponent` like this:
 | 
						|
    
 | 
						|
+makeExample('quickstart/js/app/boot.js', 'import','app/boot.js (import)')(format=".")
 | 
						|
 | 
						|
:marked
 | 
						|
  Angular is also modular. It is a collection of library modules. 
 | 
						|
  Each library is itself a module made up of several, related feature modules.
 | 
						|
  
 | 
						|
  When we need something from Angular, we use the `ng` object.
 | 
						|
  
 | 
						|
:marked
 | 
						|
  ### The Class definition object
 | 
						|
  At the bottom of the file is an empty, do-nothing class definition object for 
 | 
						|
  our `AppComponent` class.
 | 
						|
  When we're ready to build a substantive application, 
 | 
						|
  we can expand this object with properties and application logic. 
 | 
						|
  Our `AppComponent` class has nothing but an empty constructor because we 
 | 
						|
  don't need it to do anything in this QuickStart.
 | 
						|
  
 | 
						|
+makeExample('quickstart/js/app/app.component.js', 'class','app.component.js (class)')(format=".")  
 | 
						|
  
 | 
						|
:marked
 | 
						|
  ### The Component definition object
 | 
						|
  `ng.core.Component()` tells Angular that this class definition object
 | 
						|
   *is an Angular component*.
 | 
						|
  The configuration object passed to the `ng.core.Component()` method has two
 | 
						|
  fields, a `selector` and a `template`.
 | 
						|
  
 | 
						|
+makeExample('quickstart/js/app/app.component.js', 'component','app.component.js (component)')(format=".")    
 | 
						|
 | 
						|
:marked
 | 
						|
  The `selector` specifies a simple CSS selector for a host HTML element named `my-app`.
 | 
						|
  Angular creates and displays an instance of our `AppComponent`
 | 
						|
  wherever it encounters a `my-app` element in the host HTML.
 | 
						|
  
 | 
						|
.alert.is-helpful
 | 
						|
  :marked
 | 
						|
    Remember the `my-app` selector! We'll need that information when we write our `index.html`
 | 
						|
:marked
 | 
						|
  The `template` property holds the component's companion template.
 | 
						|
  A template is a form of HTML that tells Angular how to render a view.
 | 
						|
  Our template is a single line of HTML announcing "My First Angular App".
 | 
						|
  
 | 
						|
  Now we need something to tell Angular to load this component.
 | 
						|
 | 
						|
  ### Give it the boot
 | 
						|
  
 | 
						|
  Add a new file , `boot.js`, to the `app/` folder as follows:
 | 
						|
+makeExample('quickstart/js/app/boot.js', null, 'app/boot.js')(format=".")
 | 
						|
:marked
 | 
						|
  We need two things to launch the application:
 | 
						|
  1. Angular's browser `bootstrap` function
 | 
						|
  1. The application root component that we just wrote.
 | 
						|
  
 | 
						|
  We have them both in our 'namespaces'. 
 | 
						|
  Then we call `bootstrap`, passing in the **root component type**, `AppComponent`.
 | 
						|
 
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    Learn why we need `bootstrap` from `ng.platform.browser`
 | 
						|
    and why we create a separate *boot.js* file in the [appendix below](#boot).
 | 
						|
:marked
 | 
						|
  We've asked Angular to launch the app in a browser with our component at the root.
 | 
						|
  Where will Angular put it? 
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Add the `index.html`
 | 
						|
  
 | 
						|
  Angular displays our application in a specific location on our `index.html`.
 | 
						|
  It's time to create that file.
 | 
						|
 | 
						|
  We won't put our `index.html` in the `app/` folder. 
 | 
						|
  We'll locate it **up one level, in the project root folder**.
 | 
						|
  
 | 
						|
code-example(format="").
 | 
						|
  cd ..
 | 
						|
:marked
 | 
						|
  Now create the`index.html` file and paste the following lines:
 | 
						|
+makeExample('quickstart/js/index.html', null, 'index.html')(format=".")
 | 
						|
:marked
 | 
						|
  There are three noteworthy sections of HTML:
 | 
						|
 | 
						|
  1. We load the JavaScript libraries we need. `angular2-polyfills.js` and `Rx.js` are needed by Angular 2.<br/>
 | 
						|
 | 
						|
  2. We load our JavaScript files, paying attention to their order (`boot.js` needs `app.component.js` to be there first).
 | 
						|
 | 
						|
  3. We add the `<my-app>` tag in the `<body>`. **This is where our app lives!**
 | 
						|
  
 | 
						|
  When Angular calls the `bootstrap` function in `boot.js`, it reads the `AppComponent`
 | 
						|
  metadata, finds the `my-app` selector, locates an element tag named `my-app`,
 | 
						|
  and loads our application between those tags.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Compile and run!
 | 
						|
  
 | 
						|
  Open a terminal window and enter this command:
 | 
						|
code-example(format="").
 | 
						|
  npm start
 | 
						|
:marked
 | 
						|
  That command runs a static server called **lite-server** that loads `index.html` in a browser
 | 
						|
  and refreshes the browser when application files change.
 | 
						|
 | 
						|
  In a few moments, a browser tab should open and display
 | 
						|
 | 
						|
figure.image-display
 | 
						|
  img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="Output of quickstart app")
 | 
						|
 | 
						|
:marked
 | 
						|
  Congratulations!  We are in business.
 | 
						|
 | 
						|
.alert.is-helpful
 | 
						|
  :marked
 | 
						|
    If you see `Loading...` displayed instead, see the
 | 
						|
    [Browser ES6 support appendix](#es6support).
 | 
						|
:marked
 | 
						|
  ### Make some changes
 | 
						|
  
 | 
						|
  Try changing the message to "My SECOND Angular 2 app".
 | 
						|
  
 | 
						|
  `lite-server` is watching, so it should detect the change,
 | 
						|
  refresh the browser, and display the revised message.
 | 
						|
 | 
						|
  It's a nifty way to develop an application!
 | 
						|
  
 | 
						|
  We close the terminal window when we're done to terminate the server.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Final structure
 | 
						|
  Our final project folder structure looks like this:
 | 
						|
code-example(format="").
 | 
						|
  angular2-quickstart
 | 
						|
    ├── node_modules
 | 
						|
    ├── app
 | 
						|
    │    ├── app.component.js
 | 
						|
    |    └── boot.js
 | 
						|
    ├── index.html
 | 
						|
    ├── package.json
 | 
						|
    └── tsconfig.json
 | 
						|
:marked
 | 
						|
  And here are the files:
 | 
						|
+makeTabs(`
 | 
						|
    quickstart/js/app/app.component.js,
 | 
						|
    quickstart/js/app/boot.js,
 | 
						|
    quickstart/js/index.html,
 | 
						|
    quickstart/js/package.1.json
 | 
						|
  `,null,
 | 
						|
  `app/app.component.js, app/boot.js, index.html,package.json`)
 | 
						|
:marked
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Wrap Up
 | 
						|
  Our first application doesn't do much. It's basically "Hello, World" for Angular 2.
 | 
						|
 | 
						|
  We kept it simple in our first pass: we wrote a little Angular component,
 | 
						|
  we added some JavaScript libraries to `index.html`, and launched with a
 | 
						|
  static file server. That's about all we'd expect to do for a "Hello, World" app.
 | 
						|
 | 
						|
  **We have greater ambitions.**
 | 
						|
 | 
						|
  The good news is that the overhead of setup is (mostly) behind us. 
 | 
						|
  We'll probably only touch the `package.json` to update libraries.
 | 
						|
  Besides adding in the script files for our app 'modules',
 | 
						|
  we'll likely open `index.html` only if we need to add a library or some css stylesheets.
 | 
						|
 | 
						|
  We're about to take the next step and build a small application that 
 | 
						|
  demonstrates the great things we can build with Angular 2.
 | 
						|
 | 
						|
  Join us on the [Tour of Heroes Tutorial](./tutorial)!
 | 
						|
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Appendices
 | 
						|
  The balance of this chapter is a set of appendices that
 | 
						|
  elaborate some of the points we covered quickly above.
 | 
						|
  
 | 
						|
  There is no essential material here. Continued reading is for the curious.
 | 
						|
  
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  <a id="es6support"></a>
 | 
						|
  ### Appendix: Browser ES6 support
 | 
						|
  Angular 2 relies on some ES2015 features, most of them found in modern
 | 
						|
  browsers. Some browsers (including IE 11) require a shim to support the
 | 
						|
  the needed functionality.
 | 
						|
  Try loading the following shim *above* the other scripts in the `index.html`:
 | 
						|
 | 
						|
code-example(language="html" format=".").
 | 
						|
  <script src="node_modules/es6-shim/es6-shim.js"></script>
 | 
						|
:marked
 | 
						|
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  <a id="package-json"></a>
 | 
						|
  ### Appendix: package.json
 | 
						|
 | 
						|
  [npm](https://docs.npmjs.com/) is a popular package manager and Angular application developers rely on it
 | 
						|
  to acquire and manage the libraries their apps require.
 | 
						|
  
 | 
						|
  We specify the packages we need in an npm [package.json](https://docs.npmjs.com/files/package.json) file.
 | 
						|
  
 | 
						|
  The Angular team suggests the packages listed in the `dependencies` and `devDependencies`
 | 
						|
  sections listed in this file:
 | 
						|
 | 
						|
+makeJson('quickstart/js/package.1.json',{ paths: 'dependencies, devDependencies'}, 'package.json (dependencies)')(format=".") 
 | 
						|
:marked
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    There are other possible package choices. 
 | 
						|
    We're recommending this particular set that we know work well together. 
 | 
						|
    Play along with us for now. 
 | 
						|
    Feel free to make substitutions later to suit your tastes and experience.
 | 
						|
:marked
 | 
						|
  A `package.json` has an optional **scripts** section where we can define helpful
 | 
						|
  commands to perform development and build tasks. 
 | 
						|
  We've included a number of such scripts in our suggested `package.json`:
 | 
						|
+makeJson('quickstart/js/package.1.json',{ paths: 'scripts'}, 'package.json (scripts)')(format=".") 
 | 
						|
:marked
 | 
						|
  We've seen how we can run the server with this command:
 | 
						|
code-example(format="").
 | 
						|
  npm start
 | 
						|
:marked
 | 
						|
  We are using the special `npm start` command, but all it does is run `npm run lite`.
 | 
						|
  
 | 
						|
  We execute npm scripts in that manner: `npm run` + *script-name*. Here's what these scripts do:
 | 
						|
  
 | 
						|
  * `npm run lite` - run the [lite-server](https://www.npmjs.com/package/lite-server), 
 | 
						|
  a light-weight, static file server, written and maintained by [John Papa](http://johnpapa.net/) 
 | 
						|
  with excellent support for Angular apps that use routing.
 | 
						|
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  <a id="npm-errors"></a>
 | 
						|
  ### Appendix: Npm errors and warnings
 | 
						|
  
 | 
						|
  All is well if there are no console messages starting with `npm ERR!` *at the end* of an **npm install**. 
 | 
						|
  There might be a few `npm WARN` messages along the way — and that is perfectly fine.
 | 
						|
  
 | 
						|
  We often see an `npm WARN` message after a series of `gyp ERR!` messages. 
 | 
						|
  Ignore them. A package may try to re-compile itself using `node-gyp`.
 | 
						|
  If the re-compile fails, the package recovers (typically with a pre-built version)
 | 
						|
  and everything works.
 | 
						|
  
 | 
						|
  We are in good shape as long as there are no `npm ERR!` messages at the very end of `npm install`.
 | 
						|
  
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  <a id="boot"></a>
 | 
						|
  ### Appendix: ***boot.js***
 | 
						|
 | 
						|
  #### Bootstrapping is platform-specific
 | 
						|
  We use the `bootstrap` function from `ng.platform.browser`,
 | 
						|
  not `ng.core`. There's a good reason.
 | 
						|
  
 | 
						|
  We only call "core" those capabilities that are the same across all platform targets.
 | 
						|
  True, most Angular applications run only in a browser and we'll call the bootstrap function from
 | 
						|
  this library most of the time. It's pretty "core" if we're always writing for a browser.
 | 
						|
    
 | 
						|
  But it is possible to load a component in a different enviroment. 
 | 
						|
  We might load it on a mobile device with [Apache Cordova](https://cordova.apache.org/)
 | 
						|
  We might wish to render the first page of our application on the server 
 | 
						|
  to improve launch performance or facilitate 
 | 
						|
  [SEO](http://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf).
 | 
						|
 | 
						|
  These targets require a different kind of bootstrap function that we'd import from a different library.
 | 
						|
 
 | 
						|
  #### Why do we create a separate ***boot.js*** file?
 | 
						|
  
 | 
						|
  The *boot.js* file is tiny. This is just a QuickStart.
 | 
						|
  We could have folded its few lines into the `app.component.js` file
 | 
						|
  and spared ourselves some complexity.
 | 
						|
  
 | 
						|
  We didn't for what we believe to be good reasons:
 | 
						|
  1. Doing it right is easy
 | 
						|
  1. Testability
 | 
						|
  1. Reusability
 | 
						|
  1. Separation of concerns
 | 
						|
  1. We learned about import and export
 | 
						|
  
 | 
						|
  #### It's easy
 | 
						|
  Sure it's an extra step and an extra file. How hard is that in the scheme of things?
 | 
						|
  
 | 
						|
  We'll see that a separate `boot.js` is beneficial for *most* apps 
 | 
						|
  even if it isn't critical for the QuickStart.
 | 
						|
  Let's develop good habits now while the cost is low.
 | 
						|
  
 | 
						|
  #### Testability
 | 
						|
  We should be thinking about testability from the beginning
 | 
						|
  even if we know we'll never test the QuickStart. 
 | 
						|
  
 | 
						|
  It is difficult to unit test a component when there is a call to `bootstrap` in the same file.
 | 
						|
  As soon as we load the component file to test the component, 
 | 
						|
  the `bootstrap` function tries to load the application in the browser.
 | 
						|
  It throws an error because we're not expecting to run the entire application, 
 | 
						|
  just test the component. 
 | 
						|
  
 | 
						|
  Relocating the `bootstrap` function to `boot.js` eliminates this spurious error
 | 
						|
  and leaves us with a clean component module file.
 | 
						|
  
 | 
						|
  #### Reusability
 | 
						|
  We refactor, rename, and relocate files as our application evolves.
 | 
						|
  We can't do any of those things while the file calls `bootstrap`.
 | 
						|
  we can't move it. 
 | 
						|
  We can't reuse the component in another application. 
 | 
						|
  We can't pre-render the component on the server for better performance.
 | 
						|
  
 | 
						|
  #### Separation of concerns
 | 
						|
  A component's responsibility is to present and manage a view.
 | 
						|
  
 | 
						|
  Launching the application has nothing to do with view management.
 | 
						|
  That's a separate concern. The friction we're encountering in testing and reuse
 | 
						|
  stems from this unnecessary mix of responsibilities.
 | 
						|
  
 | 
						|
  #### Import/Export
 | 
						|
  
 | 
						|
  While writing a separate `boot.js` file we learned an essential Angular skill:
 | 
						|
  how to 'export' from one 'module' and 'import' into another via our simple
 | 
						|
  namespace abstraction. 
 | 
						|
  We'll do a lot of that as we learn more Angular.
 |