Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ The application is a simple contacts application where you can search, create or
- We inject our upgraded Toaster using the `@Inject` annotation.

### Step 8 - Components to Angular

*Components*
- Convert all the components to Angular components, during this process we will need to deal with a bunch of 3rd party modules.
- For the 3rd party AngularJS `angular-ladda` module we use the Angular version `angular2-ladda`
Expand All @@ -112,3 +113,22 @@ The application is a simple contacts application where you can search, create or
- We upgrade the ui-router services so we can use them in Angular, see `ajs-upgraded-providers.ts`
- We stop using ui-router directive such as `ui-sref` and instead hard code URLS in the template.

### Step 9 - Routing & Booting Angular

*Booting*
- To use Angular router we need to stop dual booting.
- This means we can't use the upgrade module anymore and we need solutions for all the upgrades AngularJS modules.
- For the upgraded ui-router service we can just ignore since we are dropping those.
- For the Toaster AngularJS module we will use the `angular2-toaster` package.
- We also need a root `app.component` and add that to `NgModule` as a declaration aswell as a bootstrap value.
- We also need to remove the dual boot code from `NgModule`
- We add a `<base href="/">` to the index.html
- We replace `index.html` body HTML with `<app-root></app-root>`

*Routing*
- We update `app.routes` to use Angular route config instead of ui-route config.
- We need to edit the component templates so that we use the Angular Router directives such as `routerOutlet` and `routerLink` etc..
- We replace `UIRouterStateParams` with `ActivatedRoute`
- We replace `UIRouterState` with `Router` instead of `this.$state.go(...)` we use `this.router.navigate([...])`
- We add the `RouterModule` to `NgModule` and provide the routes.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
"ng-infinite-scroll": "1.2.1",
"angular-ui-router": "^0.4.2",
"angular-spinner": "^1.0.1",

"angular2-toaster": "^2.0.0",
"angular2-infinite-scroll": "^0.3.3",
"angular2-ladda": "^1.1.1",
"spin.js": "^2.3.2"
Expand Down
46 changes: 12 additions & 34 deletions src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,14 @@
import * as angular from 'angular';
import {Routes} from "@angular/router";

angular
.module('codecraft')
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('list', {
url: "/",
views: {
'main': {
template: '<person-list></person-list>',
},
'search': {
template: '<search></search>',
}
}
})
.state('edit', {
url: "/edit/:email",
views: {
'main': {
template: '<person-edit></person-edit>'
}
}
})
.state('create', {
url: "/create",
views: {
'main': {
template: '<person-create></person-create>'
}
}
});
import {SearchComponent} from "./components/search.component";
import {PersonListComponent} from "./components/person-list.component";
import {PersonCreateComponent} from "./components/person-create.component";
import {PersonEditComponent} from "./components/person-edit.component";

$urlRouterProvider.otherwise('/');
});
export const routes: Routes = [
{path: '', redirectTo: '/list(header:search)', pathMatch: 'full'},
{path: 'list', component: PersonListComponent},
{path: 'search', component: SearchComponent, outlet: 'header'},
{path: 'create', component: PersonCreateComponent},
{path: 'edit/:email', component: PersonEditComponent},
];
44 changes: 44 additions & 0 deletions src/app/components/app-root.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {Component} from "@angular/core";

@Component({
selector: 'app-root',
template: `
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand"
href="/">Contacts
</a>
</div>

<router-outlet name="header"></router-outlet>

<div class="collapse navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li [routerLinkActive]="['active']">
<a [routerLink]="['']">Search</a>
</li>
<li [routerLinkActive]="['active']">
<a [routerLink]="[{outlets: {primary: 'create', header: null}}]">Create</a>
</li>
</ul>
</div>

</div>
</nav>

<div class="container main-content">

<toaster-container></toaster-container>

<div class="row">

<router-outlet></router-outlet>

</div>
</div>
`
})
export class AppRootComponent {

}
2 changes: 1 addition & 1 deletion src/app/components/card.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {ContactService} from "../services/contact.service";
</p>

<a class="btn btn-default btn-sm"
[attr.href]="'#!/edit/' + user.email">
[routerLink]="['/edit', user.email]">
<i class="fa fa-pencil"></i>
&nbsp;Edit
</a>
Expand Down
1 change: 1 addition & 0 deletions src/app/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ import "./person-list.component";
import "./card.component";
import "./spinner.component";
import "./search.component";
import "./app-root.component";
20 changes: 6 additions & 14 deletions src/app/components/person-create.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as angular from "angular";

import {Component, Inject} from "@angular/core";
import {downgradeComponent} from "@angular/upgrade/static";
import {Router} from "@angular/router";
import {ContactService} from "../services/contact.service";
import {UIRouterStateParams, UIRouterState} from "../ajs-upgraded-providers";

@Component({
selector: 'personCreate',
Expand All @@ -13,22 +12,15 @@ export class PersonCreateComponent {
public mode: string = 'Create';
public person = {};

constructor(@Inject(UIRouterStateParams) private $stateParams,
@Inject(UIRouterState) private $state,
private contacts: ContactService) {
this.person = this.contacts.getPerson(this.$stateParams.email);
constructor(private contacts: ContactService,
private router: Router) {
this.person = {};
}

save() {
this.contacts.createContact(this.person)
.then(() => {
this.$state.go("list");
this.router.navigate(['']);
})
}
}

angular
.module('codecraft')
.directive('personCreate', downgradeComponent({
component: PersonCreateComponent
}) as angular.IDirectiveFactory);
}
31 changes: 14 additions & 17 deletions src/app/components/person-edit.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as angular from "angular";

import {Component, Inject} from "@angular/core";
import {downgradeComponent} from "@angular/upgrade/static";
import {Router, ActivatedRoute} from "@angular/router";
import {ContactService} from "../services/contact.service";
import {UIRouterStateParams, UIRouterState} from "../ajs-upgraded-providers";


@Component({
selector: 'personEdit',
templateUrl: 'app/components/person-modify.component.html'
Expand All @@ -13,30 +12,28 @@ export class PersonEditComponent {
public mode: string = 'Edit';
public person: any;

constructor(@Inject(UIRouterStateParams) private $stateParams,
@Inject(UIRouterState) private $state,
private contacts: ContactService) {
this.person = this.contacts.getPerson(this.$stateParams.email);
constructor(private contacts: ContactService,
private route: ActivatedRoute,
private router: Router) {
this.route.params.subscribe(params => {
console.log(params);
if (params['email']) {
this.person = this.contacts.getPerson(params['email']);
}
});
}

save() {
this.contacts.updateContact(this.person)
.then(() => {
this.$state.go("list");
this.router.navigate(['']);
})
}

remove() {
this.contacts.removeContact(this.person)
.then(() => {
this.$state.go("list");
this.router.navigate(['']);
})
}
}

angular
.module('codecraft')
.directive('personEdit', downgradeComponent({
inputs: ['mode'],
component: PersonEditComponent
}) as angular.IDirectiveFactory);
}
37 changes: 18 additions & 19 deletions src/app/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ import {HttpModule} from '@angular/http';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {InfiniteScrollModule} from 'angular2-infinite-scroll';
import {LaddaModule} from "angular2-ladda/module/module";
import {RouterModule} from "@angular/router";
import {ToasterModule} from 'angular2-toaster';

import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';

import {
toasterServiceProvider,
uiRouterStateParamsProvider,
uiRouterStateProvider
} from "./ajs-upgraded-providers"
import {routes} from './app.routes'

import {Contact} from "./services/contact.resource";
import {ContactService} from "./services/contact.service";
Expand All @@ -43,6 +42,7 @@ import {PersonListComponent} from "./components/person-list.component";
import {PersonEditComponent} from "./components/person-edit.component";
import {PersonCreateComponent} from "./components/person-create.component";
import {SearchComponent} from "./components/search.component";
import {AppRootComponent} from "./components/app-root.component";

import {DefaultImagePipe} from "./pipes/default-image.pipe";

Expand All @@ -55,7 +55,9 @@ import {DefaultImagePipe} from "./pipes/default-image.pipe";
LaddaModule,
FormsModule,
ReactiveFormsModule,
InfiniteScrollModule
InfiniteScrollModule,
ToasterModule,
RouterModule.forRoot(routes, {useHash: true})
],
declarations: [
CardComponent,
Expand All @@ -64,33 +66,30 @@ import {DefaultImagePipe} from "./pipes/default-image.pipe";
DefaultImagePipe,
PersonEditComponent,
PersonCreateComponent,
SearchComponent
SearchComponent,
AppRootComponent
],
entryComponents: [
CardComponent,
SpinnerComponent,
PersonListComponent,
PersonEditComponent,
PersonCreateComponent,
SearchComponent
SearchComponent,
AppRootComponent
],
providers: [
Contact,
ContactService,
toasterServiceProvider,
uiRouterStateParamsProvider,
uiRouterStateProvider
ContactService
],
bootstrap: [
AppRootComponent
]
})
export class AppModule {
// Override Angular bootstrap so it doesn't do anything
ngDoBootstrap() {
}
}

// Bootstrap using the UpgradeModule
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
console.log("Bootstrapping in Hybrid mode with Angular & AngularJS");
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.body, ['codecraft']);
platformBrowserDynamic().bootstrapModule(AppModule).then(() => {
console.log("Bootstrapping Angular");
});
4 changes: 2 additions & 2 deletions src/app/services/contact.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import * as angular from 'angular';

import {Injectable, Inject} from "@angular/core";
import {downgradeInjectable} from '@angular/upgrade/static';
import {Toaster} from "../ajs-upgraded-providers";
import {Contact} from "./contact.resource";
import {ToasterService} from 'angular2-toaster';

@Injectable()
export class ContactService {
Expand All @@ -18,7 +18,7 @@ export class ContactService {
public ordering = 'ASC';


constructor(private contact: Contact, @Inject(Toaster) private toaster) {
constructor(private contact: Contact, private toaster: ToasterService) {
this.loadContacts();
}

Expand Down
Loading