We’ve been putting off using Angular2 for any larger production work because it was so top-heavy. Just the angular files were 3 meg, so the initial load was simply unacceptable. Of course, you can minify and bundle, but even then, it still was loaded with a bunch of data you really didn’t need. Finally, there is “Tree Shaking”, which was always a bit of a dream, but seemed to always fall apart on larger projects and simply blow everything up; costing us tens of thousands of dollars on developers rooting around looking for the problems in ugly javascript files.
Angular CLI is just Magic.
I’m going to assume you have Node 9.5 or greater installed as well as Git. If you’re learning this, you already do.
npm install -g @angular/cli
once installed, you pick a name for your project. I’ve been planning on making a simple tracking system for a small auto-body business, allowing their clients to see the status of the repairs.
ng new repair-track
Now, that takes a while. It checks to make sure you have git installed.
Once it’s done, you can start it up by going to that directory and just typing
ng serve --open
That will compile everything and boom, a window on localhost:4200 will pop up in your browser saying ‘app works!’.
Pretty damn cool.
Now, if you go into the root directory of repair-track (or whatever you called it), and type: “code .” (that period tells vscode that you want to open that directory) You can now see the entire starter project in place.
-Get ready, it’s going to get even cooler-
So, open up a component. The only one there is /src/app/app.component.ts and all its associated files. You’ll see that it’s got the title, “app works!” and the only variable in the component. Are you ready? Just change that to something else. I changed mine to “Welcome to Repair-Track”. Now, pop over to your browser window and, ta-da, it’s changed.
You think that’s cool? Nope. We’re still getting to cool.
Angular-CLI has actually bundled it all up for us into the following files and ripped out all the crap we don’t need:
inline.bundle.js
polyfills.bundle.js
styles.bundle.js
vendor.bundle.js
main.bundle.js
That’s very cool. Personally, I think that’s about the coolest thing about it so far. It has bundled it all up into the angular code necessary, plugins, our own code and….. check it out… our CSS. That’s right. The CSS has actually been brought into javascript so it can be applied dynamically.
Still…. that vendor.bundle.js has a TON of code in it. It’s actuall 3.5 Meg. Seriously? There’s no way all that is used, so how do we trim it down?
Well, you simply type
ng build --prod
That builds the entire project, rips out all the stuff you don’t need (tree-shaking), and minifies it, then copys those files into the /dist folder at the root directory.
Seriously…. that’s pretty cool.
This was my first CLI project. I started it about an hour ago: installed cli, created a project, modifed a component, previewed in dev mode, transpiled, tree-shook, and minified for distribution – and then previewed (I just went it that folder and typed “lite-server” (a very nice tool by John Papa)
BOOTSTRAP
So, I like Bootstrap, but with Angular2, you don’t want to use the regular bootstrap, since it is dependant on the bootstrap.js, which is then dependant upon jquery.js. There’s an Angular version you can install like this:
npm install ng2-bootstrap bootstrap –save
(here are some details on that: https://github.com/valor-software/ng2-bootstrap/blob/development/docs/getting-started/ng-cli.md)
This works great, except…. the bootstrap html selectors don’t work. However, all the grid classes and layout classes that I use work for me just fine.
Next, I use a lot of routes. I can’t stand hitting “back” and realizing I just left a SPA entirely. I also have clients that want to go directly to a work order or something like that, so they store a link or emailing invoices, etc…
The CLI module isn’t really ready for routes, so you can use the angular.io method. It isn’t immediately intuitive, but you’ll figure it out pretty quickly:
First, add a couple components using ng generate component [some name]
Now, if you have app.module.ts open, close it and open it again, just to make sure you have the latest version (I got trapped by this and had to fiddle with it)
add this to the app.module.ts file:
at the top, with the other file imports:
import { RouterModule, Routes } from ‘@angular/router’;
now, beneath your imports and above your @NgModule declaration, set your routes as a const:
const appRoutes: Routes = [
{ path: ‘path-A’, component: HeaderComponent },
{ path: ‘vehicle/:id’, component: VehicleComponent },
{
path: ‘vehicle’,
component: VehicleListComponent,
data: { title: ‘Heroes List’ }
},
{ path: ”,
redirectTo: ‘/’,
pathMatch: ‘full’
},
{ path: ‘**’, component: PageNotFoundComponent }
];
Then, in your @NgModule, under the “Imports” settings, include that constant like this: RouterModule.forRoot(appRoutes)
Here’s mine so far:
@NgModule({
declarations: [
AppComponent,
HeaderComponent,
FooterComponent,
VehicleComponent,
VehicleListComponent,
PageNotFoundComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot(appRoutes)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Ok, now we have the routes, but we actually need a place to display them. Now, your “root” page is what you have listed as the “bootstrap” in your @NgModule That’s going to come up first. Period. So, within that, you will display your routed components. I’d recommend that you put a header and footer component on that page. Right between them, is where your site is going to live. The router component uses a selector called
It is essentially going to change that to whatever component you have in the appRoutes. Got it? You type whatever route you want, it goes and finds the component that matches that route and puts it in the router-outlet, as if it is that component’s selector.
Now, you need to be able to get data from it. Routes are really good at doing things like purchase-order-list/view-order/123 So, you could type that in to the url and it would get to that order. They way you do that is by adding a variable to the route like this: ‘/vehicle/:id’. The item after that colon is a variable and will get sent to the component (if you import it!). In my case, I’m looking at a list of cars and then I want to be able to select a car and look at the details.
Here’s how you get that id into the component so you can use it:
At the top of your component, you add
import {ActivatedRoute} from ‘@angular/router’;
Now, you need to get that ActivedRoute into your component, so you add it to the “constructor(){}” like this:
id:number;
constructor(route: ActivatedRoute) {
this.id = route.snapshot.params[‘id’];
}
That’s it. Now you “have it”. You’ve declared the id as a public variable, which means you can access it from the template by putting it in the double curly braces or any of a million other ways to display it. {{id}} will show you the value passed from the URL. (note, typescript will enforce that it is a number, but people can type whateve they wan tin the URL and javascript isn’t doing any checking, so if it is something touchy, make sure to validate your routes.
Now, you’ve pretty much got the basics to build a pretty complicated website. Honestly, I’ve been putting off Angular 2 because it was SOOOO heavy. Already, AngularJS seems a bit slow on the load and I’d been building hacks to speed it up. Now, with this bundling, minification, and tree-shaking, A2 is super fast. Very very slick.