Angular 2

Migration from Angular 2 Beta 3 to Beta 7

I was recently working on getting Angular 2 up and running in a new project and hit some issues getting typescript to compile. I had been using beta 3 on samples for this blog.  The issues I was having are with typescript trying to build and resulting in multiple TS2304 errors similar to “Build: Cannot find name ‘x'”.

I am going to go over the update process first and then the fix for the typescript build issue.

Upgrade

In the dependencies section of the project’s package.json file the following versions need to be updated to the versions listed.

"dependencies": {
  "angular2": "2.0.0-beta.7",
  "systemjs": "0.19.22",
  "es6-promise": "^3.1.2",
  "es6-shim": "^0.33.4",
  "reflect-metadata": "0.1.2",
  "rxjs": "5.0.0-beta.2",
  "zone.js": "0.5.15"
}

Not a lot of changes, but this is also the point that the build typescript build errors kick in. This reference application I found from Dan Wahlin was a huge help it tracking down what the issue was.

Fixing TS2304 Errors

The errors I was getting related mostly to promise and map which turns out to be related to es6-shim. Turns out this issues can be fixed by adding a typings references for es6-shim.

In package.json add a reference to typings in the devDependencies section. Here is an example from my project.

"devDependencies": {
  "es6-module-loader": "^0.17.8",
  "gulp": "3.8.11",
  "gulp-concat": "2.5.2",
  "gulp-cssmin": "0.1.7",
  "gulp-uglify": "1.2.0",
  "rimraf": "2.2.8",
  "jspm": "0.16.15",
  "typings": "^0.6.8"
}

Next from a console run typings init  to get typings setup for the project. This adds a typings.json file. If you are already using typing this step can be skipped. If you were previously using TSD then make sure to check out the typings upgrade command handle converting your project to the new format.

Now the typing for es6-shim can be installed by running typings install es6-shim –ambient –save in the console.

Finally add two new lines to the exclude section of the tsconfig.json file for main and main.d.ts. This prevents duplicate identifier errors.

"exclude": [
  "node_modules",
  "typings/main",
  "typings/main.d.ts"
]

After the above changes the project is now running on beta 7 of Angular 2. I updated the reference application on GitHub with the changed from this post and which can be found here.

If you hit any issues during your upgrade to beta 7 please leave a comment.

Migration from Angular 2 Beta 3 to Beta 7 Read More »

Angular 2 vs Aurelia Basic Syntax

The ASP.NET Core project with Angular 2 and Aurelia from last week’s post now has feature parity between Angular 2 and Aurelia. With the applications in sync now is a good time to compare syntax for basic operations between the two frameworks.

Templates

Function Angular 2 Aurelia
Binding {{title}}  ${title}
Input Binding <input [(ngModel)]="contact.Name">  <input value.bind="contact.Name">
Loops *ngFor="#contact of contacts"  repeat.for="contact of contacts"
Events (click)="onSelect(contact)"  click.delegate="$parent.select(contact)"
Conditional Elements <div *ngIf="contact">  <div if.bind="contact">
Conditional CSS [class.selected]="contact === selectedContact"  class="${contact === $parent.selectedContact ? 'selected' : "}"
Component Rendering <contact-detail [contact]="selectedContact"></contact-detail>  <contact-detail contact.bind="selectedContact"></contact-detail>

Component Lifecycle Hooks

The hooks provided by the frameworks don’t exactly line up, but the following is a list with a list of hooks and descriptions taken for the docs of both frameworks. The hooks are listed in the order they are executed in the component’s lifecycle. For more details look at the docs for Angular 2 and Aurelia (search for “The Component Lifecycle”).

Angular 2

ngOnChanges Called when an input or output binding value changes
ngOnInit After the first ngOnChanges
ngDoCheck Developer's custom change detection
ngAfterContentInit After component content initialized
ngAfterContentChecked After every check of component content
ngAfterViewInit After component's view(s) are initialized
ngAfterViewChecked After every check of a component's view(s)
ngOnDestroy Just before the directive is destroyed

Aurelia

constructor() The view-model's constructor is called first.
created(owningView: View, myView: View) If the view-model implements the created callback it is invoked next. At this point in time, the view has also been created and both the view-model and the view are connected to their controller. The created callback will receive the instance of the "owningView". This is the view that the component is declared inside of. If the component itself has a view, this will be passed second.
bind(bindingContext: Object, overrideContext: Object) Databinding is then activated on the view and view-model. If the view-model has a bind callback, it will be invoked at this time. The "binding context" to which the component is being bound will be passed first. An "override context" will be passed second. The override context contains information used to traverse the parent hierarchy and can also be used to add any contextual properties that the component wants to add.
attached() Next, the component is attached to the DOM (in document). If the view-model has an attached callback, it will be invoked at this time.
detached() At some point in the future, the component may be removed from the DOM. If/When this happens, and if the view-model has a detached callback, this is when it will be invoked.
unbind() After a component is detached, it's usually unbound. If your view-model has the unbind callback, it will be invoked during this process.

The Winner?

Both Angular 2 and Aurelia continue to improve as they progress through their beta stages. Aurelia seems to be more stable at this point with little to no breaking changes since they entered beta. Angular 2 will have an initial head start with the inertia of Angular 1 which will make it an easier sell at some organizations.

As is evident by the comparison above these frameworks are taking different approaches. There is no clear winner and thankfully there doesn’t have to be. Both frameworks will be successful.

At this point in time I would be comfortable going live with a project on Aurelia. Angular 2 is making huge steps forward, but feels like it need a little more time to bake before I would want to use it in a production application.

If you had an application going live soon which would you chose?

Angular 2 vs Aurelia Basic Syntax Read More »

ASP.NET Core Project with Angular 2, Aurelia and an API

I have been exploring Aurelia and more recently Angular 2 and while doing so I thought it might be nice to run both frameworks from the same project.  My first crack at this can be found in this repo on Github.

Content

  • Contact model, a simplified version of the one used in previous blogs
  • ContactsController and related razor views created using Visual Studio’s scaffolding tools based on the contact mode
  • ContactsApiController is the end point for the Angular 2 and Aurelia applications
  • Angular 2 application that closely match the one from last week’s post
  • Aurelia application is currently just a proof that Angular 2 and Aurelia could run in the same project. This application will be updated to connect to the project’s web API.

Getting Started

Ensure that node and jspm are install.

After acquiring the code open the solution. If using Visual Studio the npm based packages will be restored automatically. If not using Visual Studio then run  npm install from the console. This will handle all the files needed by Angular 2.

Next run the jspm install -y  command to install the Aurelia related packages.

Make sure the database is created and up to date with the following two commands.

dnx ef database update -c ApplicationDbContext
dnx ef database update -c ContactsDbContext

In wwwroot open the config.js file and verify the paths section looking like the following. Jspm install seems to rewrite the github and npm portions of the paths section which removed the “../”. This is more than likely a configuration issue that I hope to fix in the future.

paths: {
  "*": "../Aurelia/*",
  "github:*": "../jspm_packages/github/*",
  "npm:*": "../jspm_packages/npm/*"
}

Finally run the angular2 gulp task from the task runner. The application should now run with no issues.

First Run

Make sure to register a new user as both the contacts controllers require an authorized user and filter down the contacts to display based on the logged in user.

The menu bar will contain links for Angular 2, Aurelia and Razor. Use the razor link to create some data. This is the generated razor views mentioned above. It is also the only way to add data through the application currently.

The Angular 2 link will of course launch the Angular 2 application that will display a list of contacts for the current user.

The  Aurelia like will launch the Aurelia application which just contains the very basic application from the getting started guide.

Going Forward

The plan is to develop the Angular 2 and Aurelia applications together. The Aurelia application will be the first to get some time to get up to the same level as the Angular 2 application.

It is also my hope that having this project will be a good reference for you when reading the examples in future blog posts.

ASP.NET Core Project with Angular 2, Aurelia and an API Read More »

Angular 2 with ASP.NET Core Web API

Updated version of this post can be found here.

This post will be expanding on the basic Angular 2 application from last week’s post to download data from an ASP.NET Core web API. This is the same contacts API used in all of my Aurelia and Web API posts.

Contact Interface

First add a contacts.ts typescript file in the Angular2 folder to hold an interface that defines a contact. This will be used as a definition of what the application expects a contact to look like. A class could be used instead of an interface if some sort of functionality was need on a contact.

export interface Contact {
    Id: number;
    Name: string;
}

Contact Service

This is the service that will be used to connect to the web API and retrieve a list of contacts.

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import {Contact} from './contact';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class ContactService {
    private _url = 'http://localhost:38218/api/contacts/';

    constructor(private http: Http) { }
    
    getContacts() {
        return this.http.get(this._url)
            .map(responce => <Contact[]>responce.json())
            .catch(error => {
                console.log(error);
                return Observable.throw(error);
            });
    }
}

The @Injectable() is required for typescript to output the proper metadata for Angular to know what need to be injected into the service. For more information on Angular’s dependency injection look here.

Http from angular2/http is a library used for http interactions. Http interaction is not included in the core of Angular and will require a dependency on a new file.

Contact is just a reference to the contact interface from above.

Observable is a reference to a rxjs type. Rxjs is a set of libraries that help with async programming and is used heavily by Angular 2.

The service’s  constructor get a reference to the http library and saves it to a http variable.

Here is just the getContacts() from above.

getContacts() {
    return this.http.get(this._url)
        .map(responce => <Contact[]>responce.json())
        .catch(error => {
            console.log(error);
            return Observable.throw(error);
        });
}

http.get returns an rxjs observable which is then processed with the rxjs map function. Map takes the json data from the http response and maps it to a contact array.

The url used here will need to be moved to configuration at some point.

App.component Changes

Imports

import {Component, OnInit} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
import {Contact} from './contact';
import {ContactService} from './contact.service';
import 'rxjs/Rx';

A couple of notes on the imports. OnInit is an Angular lifecycle hook that will be used to get a list of contacts. rxjs/Rx import the full set of rxjs libraries and is added here so they will be available to the full application level. rxjs is a fairly sizable and this should be replace with only the parts needed, but for this example the full set of libraries is easier.

AppComponent

The AppComponent class has been expanded and will server as the view model for the contact list. New properties were added for a title and an array of contacts.

A constructor was added to allow the injection of the ContactService.

Notice the class now implements OnInit and a ngOnInit function has been added. This is taking advantage of Angular’s lifecycle hooks. On initialization the class will call getContacts on the ContactService and subscribe to the returned observable and assign the values to the local contacts array.

export class AppComponent implements OnInit {
    public title = 'Contact List';
    public contacts: Contact[];

    constructor(private _contactService: ContactService) { }

    ngOnInit() {
        this._contactService.getContacts()
            .subscribe(
            contacts => {
                console.log(contacts);
                this.contacts = contacts;
            },
            error => alert(error));
    }
}

@Component

The template has expanded to display the title and contact data.

{{title}} binds the title property of the AppComponent class.

The array of contacts is shown in an unordered list. The list items are created used *ngFor which loops each item in the contacts array. When inside the li element items can be bound using {{contact.PropertyName}} as one would expect.

@Component({
    selector: 'my-app',
    template: `
              <h1>{{title}}</h1>
              <ul class="list-unstyled">
                <li *ngFor="#contact of contacts">
                  <span class="badge">{{contact.Id}}</span> {{contact.Name}}
                </li>
              </ul>
              `,
    providers: [
        HTTP_PROVIDERS,
        ContactService
    ]
})

The providers section is new and is a list of items that will be available for injection to this component and any of its child components.

app.component.ts

Here is the full app.companent.ts all together for reference.

import {Component, OnInit} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
import {Contact} from './contact';
import {ContactService} from './contact.service';
import 'rxjs/Rx';

@Component({
    selector: 'my-app',
    template: `
              <h1>{{title}}</h1>
              <ul class="list-unstyled">
                <li *ngFor="#contact of contacts">
                  <span class="badge">{{contact.Id}}</span> {{contact.Name}}
                </li>
              </ul>
              `,
    providers: [
        HTTP_PROVIDERS,
        ContactService
    ]
})
export class AppComponent implements OnInit {
    public title = 'Contact List';
    public contacts: Contact[];

    constructor(private _contactService: ContactService) { }

    ngOnInit() {
        this._contactService.getContacts()
            .subscribe(
            contacts => {
                console.log(contacts);
                this.contacts = contacts;
            },
            error => alert(error));

    }
}

ASP.NET View

The Angualr2.cshtml view that contains the angular application needs the following new script tag for the new http library.

<script src="~/Angular/http.dev.js"></script>

Gulp

The gulpfile.js needs also needs to change to move the new http.dev.js file to wwwroot as part of the angualr2:moveLibs task.

gulp.task("angular2:moveLibs", function () {
    return gulp.src([
            "node_modules/angular2/bundles/angular2-polyfills.js",
            "node_modules/systemjs/dist/system.src.js",
            "node_modules/systemjs/dist/system-polyfills.js",
            "node_modules/rxjs/bundles/Rx.js",
            "node_modules/angular2/bundles/angular2.dev.js",
            "node_modules/angular2/bundles/http.dev.js"
        ])
        .pipe(gulp.dest(paths.webroot + "Angular"));

});

Running the application should now display the list of contact returned by the web API.

Angular 2 with ASP.NET Core Web API Read More »

Angular 2 Quickstart with ASP.NET Core

Updated version of this post can be found here.

After working with Aurelia over last couple of months it seemed prudent to try out Angular 2. This post is going to cover the installation of Angular 2 and launching a basic Angular 2 application from an ASP.NET Core (the new name for ASP.NET 5) controller. Make sure to check out the official quickstart guide here.

Installation

Open the package.json file and add the following dependencies and devDependencies. This project is using gulp and is using the typescript based version of the quickstart guide which is why the gulp and typescript references are there.

  "dependencies": {
    "angular2":"2.0.0-beta.1",
    "systemjs": "0.19.16",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.0",
    "zone.js": "0.5.10"
  },
  "devDependencies": {
    "gulp": "3.9.0",
    "gulp-concat": "2.6.0",
    "gulp-cssmin": "0.1.7",
    "gulp-uglify": "1.5.1",
    "gulp-typescript": "2.10.0",
    "rimraf": "2.5.0",
    "typescript": "1.7.5"
  }

If inside Visual Studio 2015 the proper packages will be restored when package.js is saved, but outside of Visual Studio open a command prompt to the same directory as the package.js file and run npm install  which will download the required packages.

Typescript Configuration

Next add a tsconfig.json file to the project. This file marks the root of a typescript project and contains configuration setting for that project. Details on configuration options can be found here.

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "system",
    "moduleResolution": "node",
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5"
  },
  "exclude": [
    "node_modules"
  ]
}

Angular 2 Bootstrap and Basic App

Create an Angular folder in the project’s root folder. Next add a app.component.ts file which is used to manage a view. This component is super simple and was pulled from the official quickstart guide.

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }

Next add boot.ts which is used to bootstrap Angular 2.

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'

bootstrap(AppComponent);

Gulp Tasks

This is the project that was the inspiration for the gulpjs introduction post. The first task is to move the Angular 2 dependencies from the node_modules folder to an Angular folder in wwwroot  so they will be available to be served.

gulp.task("angular2:moveLibs", function () {
    return gulp.src([
            "node_modules/angular2/bundles/angular2-polyfills.js",
            "node_modules/systemjs/dist/system.src.js",
            "node_modules/systemjs/dist/system-polyfills.js",
            "node_modules/rxjs/bundles/Rx.js",
            "node_modules/angular2/bundles/angular2.dev.js"
        ])
        .pipe(gulp.dest(paths.webroot + "Angular"));

});

The next task move the js files created by the typescript compiler when a ts file is saved from the Angular folder in the root of the project to wwwroot/Angular.

gulp.task("angular2:moveJs", function () {
    return gulp.src(["Angular/**/*.js"])
        .pipe(gulp.dest(paths.webroot + "Angular/app/"));

});

The last task just runs both of the previous tasks.

gulp.task("angular2", ["angular2:moveLibs", "angular2:moveJs"])

ASP.NET Controller

The Angular application is going to be run from the ASP.NET’s HomeController. Here is the new action that will load the yet to be created view.

public IActionResult Angular2()
{
    return View();
}

ASP.NET View

This is the view that when loaded kicks off the Angular 2 application. Add a new file called Angular2.cshtml in the Views/Home folder.  In the following first Angular related scripts are loaded. Then system.js is configured and the boot module is imported and the app is rendered inside of the my-app tag.

<html>
<head>
    <title>Angular 2 QuickStart</title>

    <script src="~/Angular/angular2-polyfills.js"></script>
    <script src="~/Angular/system.src.js"></script>
    <script src="~/Angular/Rx.js"></script>
    <script src="~/Angular/angular2.dev.js"></script>

    <script>
        System.config({
            packages: {
                '../Angular': {
                    format: 'register',
                    defaultExtension: 'js'
                }
            }
        });
        System.import('../Angular/app/boot')
              .then(null, console.error.bind(console));
    </script>

</head>

<body>
    <my-app>Loading...</my-app>
</body>

</html>

This is where the trouble started for me. It took a bit of searching, but the problem turned out to be with the system.js configuration. Since the view is in the HomeController it gets rendered out of as Home/Angular2.html and this project’s Angular files are up a directory so in order for system.js to find the Angular files the package configuration needed to be set to look up one folder.

This issue took longer to find than I would like to admit, but that is the danger is using libraries one is not familiar with. System.js was not my first thought since it was used in my Aurelia without issue. If you run into an issue check out the docs for system.js configuration.

Finally add the new view to main application’s nav bar. In Views/Shared/_Layout.cshtml add a link to Angular 2 on using the Home controller.

<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
        <li><a asp-controller="Home" asp-action="Index">Home</a></li>
        <li><a asp-controller="Home" asp-action="Angular2">Angular 2</a></li>
        <li><a asp-controller="Home" asp-action="About">About</a></li>
        <li><a asp-controller="Home" asp-action="Contact">Contact</a></li>
    </ul>
    @await Html.PartialAsync("_LoginPartial")
</div>

Follow Up

This is a very basic Angular 2 application. Expect a follow up post in the new few weeks with this application build out more to utilize the same contacts web API as my Aurelia posts.

Update

If you are having issues upgrading beta 7 check out this post for a solution.

Angular 2 Quickstart with ASP.NET Core Read More »