Quickstart

JavaScript

Let's start from zero and build a super simple Angular application in JavaScript.

Don't want JavaScript?

Although we're getting started in JavaScript, you can also write Angular apps in TypeScript by selecting it from the combo-box in the banner.

See It Run!

Running the is the quickest way to see an Angular app come to life.

Clicking that link fires up a browser, loads the sample in plunker, and displays a simple message:

Output of quickstart app

Here is the file structure:

angular-quickstart
src
app
app.component.js
app.module.js
main.js
index.html
styles.css

Functionally, it's an index.html, styles.css and three 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
  2. Write the Angular root component for our app
  3. Add an Angular Module
  4. Bootstrap it to take control of the main web page
  5. Write the main page (index.html)
  6. Add some CSS (styles.css)

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.

Development Environment

We'll need a place to stand (the application project folder), some libraries and your editor of choice.

Create a new project folder

mkdir angular-quickstart cd angular-quickstart

Add the libraries we need

We recommend the npm package manager for acquiring and managing our development libraries.

Don't have npm? Get it now because we're going to use it now and repeatedly throughout this documentation.

Add a package.json file to the project folder and copy/paste the following:

package.json

{ "name": "angular-quickstart", "version": "1.0.0", "scripts": { "start": "npm run lite", "lite": "lite-server" }, "license": "MIT", "dependencies": { "@angular/common": "~2.4.0", "@angular/compiler": "~2.4.0", "@angular/core": "~2.4.0", "@angular/forms": "~2.4.0", "@angular/http": "~2.4.0", "@angular/platform-browser": "~2.4.0", "@angular/platform-browser-dynamic": "~2.4.0", "@angular/router": "~3.4.0", "@angular/upgrade": "~2.4.0", "angular-in-memory-web-api": "~0.3.1", "core-js": "^2.4.1", "rxjs": "5.0.1", "zone.js": "^0.8.4" }, "devDependencies": { "concurrently": "^3.0.0", "lite-server": "^2.2.2" } }

Itching to know the details? We explain in the appendix below

Install these packages by opening a terminal window (command window in Windows) and running this npm command.

npm install

Scary error messages in red may appear during install. Ignore them. The install will succeed. See the appendix below for more information.

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 src/app/. Execute the following command in the console window.

mkdir app cd app

Add the component file

Now add a file named app.component.js and paste the following lines:

src/app/app.component.js

(function(app) { app.AppComponent = ng.core.Component({ selector: 'my-app', template: '<h1>Hello Angular</h1>' }) .Class({ constructor: function() {} }); })(window.app || (window.app = {}));

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.

src/app/app.component.js (component schema)

app.AppComponent = ng.core.Component({ }) .Class({ });

The Component method takes a configuration object with three 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 a native module system. There are several popular 3rd party module systems we could use. Instead, for simplicity and to avoid picking favorites, we'll create a single global namespace for our application.

We'll call it app and we'll add all of our code artifacts to this one global object.

We don't want to pollute the global namespace with anything else. So within each file we surround the code in an IIFE ("Immediately Invoked Function Expression").

src/app/app.component.js (IIFE)

(function(app) { })(window.app || (window.app = {}));

We pass the global app namespace object into the IIFE, taking care to initialize it with an empty object if it doesn't yet exist.

Most application files export one thing by adding that thing to the app namespace. Our app.component.js file exports the AppComponent.

src/app/app.component.js (export)

app.AppComponent =

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:

src/app/app.module.js (import)

declarations: [ app.AppComponent ],

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.

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.

app.component.js (class)

.Class({ constructor: function() {} });

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.

app.component.js (component)

ng.core.Component({ selector: 'my-app', template: '<h1>Hello Angular</h1>' })

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.

Remember the my-app selector! We'll need that information when we write our index.html

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 "Hello Angular".

Now we need something to tell Angular to load this component.

Add an NgModule

Angular apps are composed of Angular Modules that snuggly contain all our components and everything else we need for our app.

Create the src/app/app.module.js file with the following content:

src/app/app.module.js

(function(app) { app.AppModule = ng.core.NgModule({ imports: [ ng.platformBrowser.BrowserModule ], declarations: [ app.AppComponent ], bootstrap: [ app.AppComponent ] }) .Class({ constructor: function() {} }); })(window.app || (window.app = {}));

Read more about the NgModule configuration in the appendix below.

Bootstrap it!

Add a new file , main.js, to the src/app/ folder as follows:

src/main.js

(function(app) { document.addEventListener('DOMContentLoaded', function() { ng.platformBrowserDynamic .platformBrowserDynamic() .bootstrapModule(app.AppModule); }); })(window.app || (window.app = {}));

We need two things to launch the application:

  1. Angular's platformBrowserDynamic().bootstrapModule function
  2. The application root module that we just wrote.

We have them both in our 'namespaces'. Then we call bootstrapModule, passing in the root app module, AppModule.

Learn why we need bootstrapModule from ng.platformBrowserDynamic and why we create a separate js files in the appendix below.

We've asked Angular to launch the app in a browser with our component at the root. Where will Angular put it?

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 src/app/ folder. We'll locate it up one level, in the project root folder.

cd ..

Now create theindex.html file and paste the following lines:

src/index.html

<html> <head> <title>Angular QuickStart JS</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"> <!-- 1. Load libraries --> <!-- IE required polyfill --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script> <script src="node_modules/@angular/core/bundles/core.umd.js"></script> <script src="node_modules/@angular/common/bundles/common.umd.js"></script> <script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script> <script src="node_modules/@angular/platform-browser/bundles/platform-browser.umd.js"></script> <script src="node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script> <!-- 2. Load our 'modules' --> <script src='app/app.component.js'></script> <script src='app/app.module.js'></script> <script src='main.js'></script> </head> <!-- 3. Display the application --> <body> <my-app>Loading...</my-app> </body> </html>

There are three noteworthy sections of HTML:

  1. We load the JavaScript libraries we need; learn about them below.

  2. We load our JavaScript files.

  3. We add the <my-app> tag in the <body>. This is where our app lives!

When Angular calls the bootstrapModule function in main.js, it reads the AppModule metadata, sees that AppComponent is the bootstrap component, finds the my-app selector, locates an element tag named my-app, and renders our application's view between those tags.

Add some style

Styles aren't essential but they're nice, and index.html assumes we have a stylesheet called styles.css.

Create a styles.css file in the project root folder and start styling, perhaps with the minimal styles shown below. For the full set of master styles used by the documentation samples, see styles.css.

src/styles.css

h1 { color: #369; font-family: Arial, Helvetica, sans-serif; font-size: 250%; } body { margin: 2em; } /* * See https://github.com/angular/angular.io/blob/master/public/docs/_examples/styles.css * for the full set of master styles used by the documentation samples */

Configure the server

We're going to use a static server called lite-server that loads index.html in a browser and refreshes the browser when application files change.

The static server will use the bs-config.json file as configuration. This files tells the server that src/ is the base directory to serve, and that any requests to node_modules/ should be routed to node_modules/ in the root directory instead of src/node_modules/

Run!

Open a terminal window and enter this command:

npm start

That command runs lite-server.

In a few moments, a browser tab should open and display

Output of quickstart app

Congratulations! We are in business.

If you see Loading... displayed instead, see the Browser ES2015 support appendix.

Make some changes

Try changing the message to "Hello Angular!".

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.

Final structure

Our final project folder structure looks like this:

angular-quickstart
node_modules
src
app
app.component.js
app.module.js
main.js
index.html
styles.css
bs-config.json
package.json

And here are the files:

(function(app) { app.AppComponent = ng.core.Component({ selector: 'my-app', template: '<h1>Hello Angular</h1>' }) .Class({ constructor: function() {} }); })(window.app || (window.app = {})); (function(app) { app.AppModule = ng.core.NgModule({ imports: [ ng.platformBrowser.BrowserModule ], declarations: [ app.AppComponent ], bootstrap: [ app.AppComponent ] }) .Class({ constructor: function() {} }); })(window.app || (window.app = {})); (function(app) { document.addEventListener('DOMContentLoaded', function() { ng.platformBrowserDynamic .platformBrowserDynamic() .bootstrapModule(app.AppModule); }); })(window.app || (window.app = {})); <html> <head> <title>Angular QuickStart JS</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"> <!-- 1. Load libraries --> <!-- IE required polyfill --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script> <script src="node_modules/@angular/core/bundles/core.umd.js"></script> <script src="node_modules/@angular/common/bundles/common.umd.js"></script> <script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script> <script src="node_modules/@angular/platform-browser/bundles/platform-browser.umd.js"></script> <script src="node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script> <!-- 2. Load our 'modules' --> <script src='app/app.component.js'></script> <script src='app/app.module.js'></script> <script src='main.js'></script> </head> <!-- 3. Display the application --> <body> <my-app>Loading...</my-app> </body> </html> h1 { color: #369; font-family: Arial, Helvetica, sans-serif; font-size: 250%; } body { margin: 2em; } /* * See https://github.com/angular/angular.io/blob/master/public/docs/_examples/styles.css * for the full set of master styles used by the documentation samples */ { "server": { "baseDir": "src", "routes": { "/node_modules": "node_modules" } } } { "name": "angular-quickstart", "version": "1.0.0", "scripts": { "start": "npm run lite", "lite": "lite-server" }, "license": "MIT", "dependencies": { "@angular/common": "~2.4.0", "@angular/compiler": "~2.4.0", "@angular/core": "~2.4.0", "@angular/forms": "~2.4.0", "@angular/http": "~2.4.0", "@angular/platform-browser": "~2.4.0", "@angular/platform-browser-dynamic": "~2.4.0", "@angular/router": "~3.4.0", "@angular/upgrade": "~2.4.0", "angular-in-memory-web-api": "~0.3.1", "core-js": "^2.4.1", "rxjs": "5.0.1", "zone.js": "^0.8.4" }, "devDependencies": { "concurrently": "^3.0.0", "lite-server": "^2.2.2" } }

Wrap Up

Our first application doesn't do much. It's basically "Hello, World" for Angular.

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.

Join us on the Tour of Heroes Tutorial!

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.

Appendix: Libraries

We loaded the following scripts

src/index.html

<!-- IE required polyfill --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script> <script src="node_modules/@angular/core/bundles/core.umd.js"></script> <script src="node_modules/@angular/common/bundles/common.umd.js"></script> <script src="node_modules/@angular/compiler/bundles/compiler.umd.js"></script> <script src="node_modules/@angular/platform-browser/bundles/platform-browser.umd.js"></script> <script src="node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>

We began with an Internet Explorer polyfill. IE requires a polyfill to run an application that relies on ES2015 promises and dynamic module loading. Most applications need those capabilities and most applications should run in Internet Explorer.

Next are the polyfills for Angular, zone.js and Reflect.js, followed by the Reactive Extensions RxJS library.

Our QuickStart doesn't use the Reactive Extensions but any substantial application will want them when working with observables. We added the library here in QuickStart so we don't forget later.

Finally, we loaded the web development version of Angular itself.

We'll make different choices as we gain experience and become more concerned about production qualities such as load times and memory footprint.

Appendix: package.json

npm 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 file.

The Angular team suggests the packages listed in the dependencies and devDependencies sections listed in this file:

package.json (dependencies)

{ "dependencies": { "@angular/common": "~2.4.0", "@angular/compiler": "~2.4.0", "@angular/core": "~2.4.0", "@angular/forms": "~2.4.0", "@angular/http": "~2.4.0", "@angular/platform-browser": "~2.4.0", "@angular/platform-browser-dynamic": "~2.4.0", "@angular/router": "~3.4.0", "@angular/upgrade": "~2.4.0", "angular-in-memory-web-api": "~0.3.1", "core-js": "^2.4.1", "rxjs": "5.0.1", "zone.js": "^0.8.4" }, "devDependencies": { "concurrently": "^3.0.0", "lite-server": "^2.2.2" } }

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.

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:

package.json (scripts)

{ "scripts": { "start": "npm run lite", "lite": "lite-server" } }

We've seen how we can run the server with this command:

npm start

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:

Appendix: npm errors and warnings

All is well if there are no console messages starting with npm ERR! at the end of 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.

Just make sure there are no npm ERR! messages at the very end of npm install.

Appendix: NgModule

The NgModule decorator is listing:

  1. What other Angular Modules ours uses
  2. Which components and directives we declare in our components
  3. The component to bootstrap at the start

We import our lone app.AppComponent and add it to both declarations and bootstrap array.

Notice that we also add ng.platformBrowser.BrowserModule to the imports array. This is the Angular Module that contains all the needed Angular bits and pieces to run our app in the browser.

Angular itself is split into separate Angular Modules so we only need to import the ones we really use.

One of the most common ones is FormsModule, and soon we'll also see RouterModule and HttpModule.

Appendix: main.js

Bootstrapping is platform-specific

We use the platformBrowserDynamic().bootstrapModule function from ng.platformBrowserDynamic, 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 environment. We might load it on a mobile device with Apache Cordova or NativeScript. We might wish to render the first page of our application on the server to improve launch performance or facilitate SEO.

These targets require a different kind of bootstrap function that we'd import from a different library.

Why do we create a separate main.js, app.module.js and app.component.js files?

The main.js file is tiny. This is just a QuickStart. We could have folded its few lines into the app.module.js file, and that one into app.component.js and spared ourselves some complexity.

We didn't for what we believe to be good reasons:

  1. Doing it right is easy
  2. Testability
  3. Reusability
  4. Separation of concerns
  5. 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 main.js and app.module.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 bootstrapModule in the same file. As soon as we load the component file to test the component, the bootstrapModule 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 bootstrapModule function to main.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 bootstrapModule. 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, and a NgModule's reponsibility is to define the application context.

Launching the application has nothing to do with any of these. 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 main.js and app.module.js files 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.