Typescript

Angular 2 with an ASP.NET Core API

This week’s post is going to take the Angular 2 application from a couple of weeks ago and add the same functionality currently present in the Aurelia application found the ASP.NET Core Basic repo. This release is the starting point for the solution used in this post.

Starting point overview

When you download a copy of the repo you will find an ASP.NET Core solution that contains three projects. The Angular project is where this post will be focused.

The Contacts project has a set of razor views and a controller to go with them that support standard CRUD operations, which at the moment is the best way to get contact information in the database. It also contains the ContactsApiController which will be the controller used to feed contacts to the Angular 2 and Aurelia applications.

Multiple startup projects in Visual Studio

In order to properly test the functionality that will be covered here both the Contacts project and the Angular project will need to be running at the same time. Visual Studio provides a way to handle this. The Multiple startup projects in Visual Studio section of this post walks through the steps of setting up multiple startup project. The walk through is for the Aurelia project, but the same steps can be applied to the Angular project.

Model

Create a contacts directory inside of ClientApp/app/components/ of the Angular project. Next create a contact.ts file to the contacts directory. This file will be the model of a contact in the system. If you read the Aurelia version of this post you will noticed that this model is more fully defined since this project is using TypeScript the more fully defiled model provides more type safety. The following is the contests file.

export class Contact {
    id: number;
    name: string;
    address: string;
    city: string;
    state: string;
    postalCode: string;
    phone: string;
    email: string;

    constructor(data) {
        Object.assign(this, data);
    }

    getAddress() {
        return `${this.address} ${this.city}, ${this.state} ${this.postalCode}`;
    }

}

Service

To isolate HTTP access the application will use a service to encapsulate access to the ASP.NET Core API. For the service create a contact.service.ts file in the contacts directory of the Angular project. The following is the code for the service.

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Contact } from './contact';

@Injectable()
export class ContactService {

    constructor(private http: Http) {
    } 

    getAll(): Promise<Contact[]> {
        return this.http.get('http://localhost:13322/api/contactsApi/')
            .toPromise()
            .then(response => response.json())
            .then(contacts => Array.from(contacts, c => new Contact(c)))
            .catch(error => console.log(error));
    }
}

This class uses Angular’s HTTP client to access the API and download a list of contacts. Angular’s HTTP client uses reactive extensions and returns an observable. In this case we don’t need an observable so for this service the observable is being converted to a promise. Then from there the response from the API is being converted an array of type contact.

Also make note of the Injectable decorator which tells Angular 2 the class should be available for dependency injection.

View Model

The next step is to create a view model to support the view that will be used to display the contacts download from the API. Add a file named contactlist.component.ts to the contacts directory of the Angular project. The following is the full contents of the view model file. This will be followed by a breakdown of the file in order to highlight some parts of the file.

import { Component, OnInit } from '@angular/core';
import { Contact } from './contact';
import { ContactService } from './contact.service';

@Component({
    selector: 'contactlist',
    template: require('./contactlist.component.html'),
    providers: [ContactService]
})
export class ContactListComponent implements OnInit {
    contacts: Contact[];

    constructor(private contactService: ContactService) { }

    ngOnInit(): void {
        this.contactService.getAll()
            .then(contacts => this.contacts = contacts);
    }
}

The import statements are pulling in a couple parts of the Angular 2 framework in addition to the contact model and contact service created above.

Next is a component decorator which marks the class as an Angular component and provides a method to set metadata about the class.

@Component({
    selector: 'contactlist',
    template: require('./contactlist.component.html'),
    providers: [ContactService]
})

The selector property sets the identifier for the class to be used in templates. The template property sets the view that should be used with the view model. In this case it is requiring in another file, but it could also contain the actual template that should be used to render the component. An alternate is to use templateUrl to point to an external file containing a template. The final property used in this example is the providers  property which is a list of providers that the framework needs to be made available to the component, in this case the ContractService. For more information on the component decorator check out the Angular docs.

The next thing of note on this class is that it implements OnInit.

export class ContactListComponent implements OnInit

OnInit is one of Angular’s lifecycle hooks, see the docs for the rest of the available hooks. OnInit is called once after component creation and runs the ngOnInit function which in the case of this class is being used to get a list of contacts from the ContactService.

View

For the view create a contactlist.component.html in the contacts directory of the Angular project. This is the file that the veiw model created above is bound with to display the contact data retrieved from the API. The following is the complete contents of the view file.

<ul>
    <li *ngFor="let contact of contacts">
        <h4>{{contact.name}}</h4>
        <p>{{contact.getAddress()}}</p>
    </li>
</ul>

The second line repeats the li tag for each contact in the contacts array of the view model class. {{expression}} is Angular’s syntax for one way data binding. {{contact.name}} does a one way binding to the name property of the current contact in the *ngFor loop. For more details on the different options available for data binding see the docs.

Add menu

The final piece is to add an item to the menu from with the contact list can be accessed. Open app.module.ts in the ClientApp/app/components/ directory. Add an imports for the ContactListComponent.

import { ContactListComponent } from './components/contacts/contactlist.component';

Next add a new path to the RouterModule. The third from the bottom is the line that was added for the contact list.

RouterModule.forRoot([
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: 'home', component: HomeComponent },
    { path: 'counter', component: CounterComponent },
    { path: 'fetch-data', component: FetchDataComponent },
    { path: 'contact-list', component: ContactListComponent },
    { path: '**', redirectTo: 'home' }
])

Finally open the navmenu.component.html file in the ClientApp/app/components/navmenu/  directory. Add a new li for the contact list matching the following.

<li [routerLinkActive]="['link-active']">
    <a [routerLink]="['/contact-list']">
        <span class='glyphicon glyphicon-list-alt'></span> Contact List
    </a>
</li>

Wrapping up

That is all it takes to consume some data from an ASP.NET Core API and use it in an Angular 2 application. I can’t stress enough how easy working with in the structure provided by JavaScriptServices helped in getting this project up and going quickly.

The completed code that goes along with this post can be found here. Also note that the Aurelia project has be redone as well also based on JavaScriptServices and TypeScript so that the applications will be easier to compare.

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

Angular 2 Template Driven Validation

Last week’s post covered model driven validation in Angular 2 and this week I will be looking at template driven validation. Template driven validation provides a simplified way to add validation without the need to directly use a control group. This is a great way to get up and running for simple form cases, and maybe more complex ones as well. I haven’t hit a case yet that wouldn’t work with either validation style.

Building a Template Form with Validation

I started with a simple form that contains labels and inputs for entering a name and email address that are bound to corresponding values in the associated model.

<form>
   <div class="form-group">
     <label for="name">Name</label>
     <input type="text" class="form-control" [(ngModel)]="name">
   </div>
   <div class="form-group">
     <label for="name">Email</label>
     <input type="text" class="form-control" [(ngModel)]="email">
   </div>
</form>

The next example is the same form with validation added.

<form #contactForm="ngForm">
   <div class="form-group">
     <label for="name">Name</label>
     <input type="text" class="form-control" ngControl="name" #nameControl="ngForm" [(ngModel)]="name" required minlength="3">
     <div [hidden]="nameControl.valid || !nameControl.errors || !nameControl.errors.required">Name is required</div>
     <div [hidden]="nameControl.valid || !nameControl.errors || !nameControl.errors.minlength">Min Length</div>
   </div>
   <div class="form-group">
     <label for="name">Email</label>
     <input type="text" class="form-control" ngControl="email" #emailControl="ngForm" [(ngModel)]="email" required>
     <div [hidden]="emailControl.valid || !emailControl.errors || !emailControl.errors.required">Email is required</div>
   </div>
</form>

The first change you will notice is that the form now has a name assigned using #contactForm=”ngForm”. In this case the name is not used, but it could be used to disable a submit button if any of the inputs the form contained didn’t have valid values. I am sure there are a lot more use cases as well.

On the inputs that need validation a controls name is assigned via ngControl=”name” and a name is assigned using #nameControl=”ngForm”. I had some trouble withe assigning names to my inputs at first I keep getting the following.

EXCEPTION: Cannot assign to a reference or variable!

The cause of the issue was that I was trying to use #name for the control name which was already a property on the model. Once I changed to #nameControl all worked fine.

For the input for name above required minlength=”3″ tells the Angular form that the input is required and must be at least three characters in length.

Displaying Validation

For the name input you can see that it has two divs used to show specific messages based on which validation condition failed.

<div [hidden]="nameControl.valid || !nameControl.errors || !nameControl.errors.required">Name is required</div>
<div [hidden]="nameControl.valid || !nameControl.errors || !nameControl.errors.minlength">Min Length</div>

I am not sure why, but when using the template style validation I had to check !nameControl.errors in addition to the specific error like !nameControl.errors.required or I would get an exception when the page tried to load. If your control doesn’t have more than a single validation then nameControl.valid would be a sufficient condition for showing validation messages.

Custom Validators

I am going to use the same email validator from last week with a few changes so can be used from a template. The following is the full class.

import {Control, NG_VALIDATORS, Validator} from '@angular/common';
import {Directive, Provider, forwardRef} from '@angular/core';

const EMAIL_VALIDATOR = new Provider(NG_VALIDATORS, { useExisting: forwardRef(() => EmailValidator), multi: true });

@Directive({
    selector: '[emailValidator]',
    providers: [EMAIL_VALIDATOR]
})
export class EmailValidator implements Validator {
    validate(control: Control): {[key: string]: any} {
        const emailRegexp = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
        if (control.value !== null && control.value !== "" && (control.value.length <= 5 || !emailRegexp.test(control.value))) {
            return { "email": true };
        }
        return null;
    }
}

The biggest difference is the @Directive decorator. The selector is the attribute that will be used to mark that an input needs to pass the specified validation. I am not 100% sure of the specifics of the provider, but the above works. This is another topic I need to explore more.

Using a Custom Validator

First in the model the validator must be imported.

import {EmailValidator} from './email-validator';

Then the validator needs to be added to the directives section of the @Component decorator.

@Component({
    selector: 'contact-detail',
    templateUrl: 'contact.detail.html',
    directives: [
        EmailValidator
    ],
    providers: [
        HTTP_PROVIDERS
    ]
})

To use in the view just add the emailValidator selector to the proper input.

<input type="text" class="form-control" ngControl="email" #emailControl="ngForm" [(ngModel)]="email" required emailValidator>

Finally add a div to display the error.

<div [hidden]="emailControl.valid || !emailControl.errors || !emailControl.errors.email">Email is invalid</div>

Wrapping Up

Using template driven validation you can quickly get a form validated without having to make changes outside of your template (unless you are using a custom validator). Angular 2 offers a lot of options when it comes to validation and where it should be put.

Angular 2 Template Driven Validation Read More »

Angular 2 Model Driven Validation

In this post a couple of weeks ago I covered Aurelia’s new validation plugin and I thought it would be good to see what Angular 2 has to offer validation wise. Angular’s offering is vastly different that Aurelia. Angular can use model driven or template driven validations. This post is going to look at the model driven style.

Forms

Angular forms is the framework’s way to handle groups of data entry that need support for data binding and validation among other things.

Building a Form with Validation

The first step to building a model driven form is import the classes that will be needed.

import {FormBuilder, ControlGroup, Validators} from '@angular/common';

Next add a variable for control group and setup the control group in the constructor of the class.

public contactForm: ControlGroup;

constructor(formBuilder: FormBuilder) {
    this.contactForm = formBuilder.group({
        name: ["", Validators.compose([Validators.required, Validators.minLength(3)])],
        email: ["", Validators.required]
    });
}

The above uses FormBuilder to define a name property that is required with a minimum length of three characters and an email property that is required. Later in the post I will add better email validation via customer validator.

Angular 2 only comes with required, minimum length, max length and pattern (match given regex) validators out of the box. Thankfully custom validators are pretty easy to implement.

Using a From with a View

Now that the form is setup the view needs to utilize it. The following is the code form the view.

<form class="form-horizontal" [ngFormModel]="contactForm">
  <div class="form-group">
      <label class="control-label">Name</label>
      <input type="text" ngControl="name" #name="ngForm" class="form-control">
      <div [hidden]="name.valid || name.pristine || !name.errors.required">Required</div>
      <div [hidden]="name.valid || name.pristine || !name.errors.minlength">Min Length</div>
  </div>
  <div class="form-group">
      <label class="control-label">Email</label>
      <input type="email" ngControl="email" #email="ngForm" class="form-control">
      <div [hidden]="email.valid || email.pristine || !email.errors.required">Required</div>
  </div>
</form>

First notice in the form tag [ngFormModel]=”contactForm” is used to bind the form to the control group crated in the model.

Instead of [(ngModel)]=”name” we use ngControl=”name” to bind the input box to the name control in the control group that was crated using the form builder above. #name=”ngForm” defines name as a variable that can be used later.

<div [hidden]=”name.valid || name.pristine || !name.errors.required”>Required</div>  is used to display validation errors to the user. This code is just saying to hide the div if name is valid or pristine (not changed by the user)  or if the validation error is not because the field is required. While this style works I much prefer Aurelia as it handles the extra work needed to automatically display validation errors.

Custom Validators

As I mention above I am going to show you a custom validator that can be used to better handle email validation. Most of this validation I found in a search but unfortunately I forgot to save the URL so I can’t link to the exact source. The following is the complete code for a custom email validator.

import {Control} from '@angular/common';

export class EmailValidator {
    static email(control: Control) {
        const emailRegexp = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;

        if (control.value !== "" && (control.value.length <= 5 || !emailRegexp.test(control.value))) {
            return { "email": true };
        }

        return null;
    }
}

Note that returning null means that validation passed.

Using a Custom Validator in a Model

First the custom validator needs to be imported.

import {EmailValidator} from './email.validator';

Now the validator can be used in the classes form builder.

this.contactForm = formBuilder.group({
    name: ["", Validators.compose([Validators.required, Validators.minLength(3)])],
    email: ["", Validators.compose([Validators.required, EmailValidator.email])]
});

Notices that the email control is now using Validators.compose which is used to apply multiple validations to a single control.

Using a Custom Validator in a View

Now the view just has to be changed to show the user that the reason for the failed validation is an invalid email address.

<div class="form-group">
    <label class="control-label">Email</label>
    <input type="email" ngControl="email" #email="ngForm" class="form-control">
    <div [hidden]="email.valid || email.pristine || !email.errors.required">Required</div>
    <div [hidden]="email.valid || email.pristine || !email.errors.email">Invalid address</div>
</div>

Note that the entry in errors will match the return value from the custom validator. I had issues trying to use the minimum length validator because I was trying to use minLength instead of minlength. If you are having trouble with validation message showing up that would be the first thing to check.

Wrapping Up

That covers the basics of model driven validation in Angular 2. Be on the look out for a post in the future that covers the same concepts but using a template driven approach. I also wanted to point out this post by Pascal Precht and this post by David Den Toom which helped me a lot in writing this post.

Angular 2 Model Driven Validation Read More »

Migration from Angular 2 Betas to RC

On May 2nd Angular 2 moved from the beta stage to the release candidate stage and is currently on RC 1. The move from beta to RC was a bit more involved than the moves between beta. This post is going to cover the changes I went through to get my SPA sample application migrated to RC 1.

Update package.json

With this release Angular 2 was split from a single dependency in to multiple. The other big change is a rename of from angular2  to @angular. The following is my updated dependencies section.

"dependencies": {
  "@angular/common": "2.0.0-rc.1",
  "@angular/compiler": "2.0.0-rc.1",
  "@angular/core": "2.0.0-rc.1",
  "@angular/http": "2.0.0-rc.1",
  "@angular/platform-browser": "2.0.0-rc.1",
  "@angular/platform-browser-dynamic": "2.0.0-rc.1",
  "@angular/router": "2.0.0-rc.1",
  "@angular/router-deprecated": "2.0.0-rc.1",
  "@angular/upgrade": "2.0.0-rc.1",

  "systemjs": "0.19.27",
  "es6-shim": "^0.35.0",
  "reflect-metadata": "^0.1.3",
  "rxjs": "5.0.0-beta.6",
  "zone.js": "^0.6.12"
}

After the above change make sure to run npm install in the root of the project from a command prompt. Not sure if it was just me, but the dependency auto restore in Visual Studio wouldn’t work for the @angular dependencies.

Update gulpfile.js

Due to the changes in the dependency structure my gulpfile had to be updated to copy the new files to the proper locations. I took the opportunity to move all of my dependency to a lib folder.

gulp.task("angular2:moveLibs", function () {
    return gulp.src([
            "node_modules/@angular/common/**/*",
            "node_modules/@angular/compiler/**/*",
            "node_modules/@angular/core/**/*",
            "node_modules/@angular/http/**/*",
            "node_modules/@angular/platform-browser/**/*",
            "node_modules/@angular/platform-browser-dynamic/**/*",
            "node_modules/@angular/router/**/*",
            "node_modules/@angular/router-deprecated/**/*",
            "node_modules/@angular/upgrade/**/*",
            "node_modules/systemjs/dist/system.src.js",
            "node_modules/systemjs/dist/system-polyfills.js",
            "node_modules/rxjs/**/*",
            "node_modules/es6-shim/es6-shim.min.js",
            "node_modules/zone.js/dist/zone.js",
            "node_modules/reflect-metadata/Reflect.js"
    ],
        { base: "node_modules" })
        .pipe(gulp.dest(paths.webroot + "Angular/lib"));

});

If you were using the previous version of my gulp take make sure to remove the old dependencies from the wwwroot/Angular/ folder.

Update Entry Point View

Again because of the dependency changes the entry point view for the Angular 2 application needed changes which is Angular2.cshtml in my project. A systemjs.config.js was added to handle the bulk of the configuration. The following is the full source for my entry point view.

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

      <script src="~/Angular/lib/es6-shim/es6-shim.min.js"></script>
      <script src="~/Angular/lib/zone.js/dist/zone.js"></script>
      <script src="~/Angular/lib/reflect-metadata/Reflect.js"></script>
      <script src="~/Angular/lib/systemjs/dist/system.src.js"></script>

      <script src="~/Angular/app/systemjs.config.js"></script>
      <script>
          System.import('app').catch(function(err){ console.error(err); });
      </script>
  </head>

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

Add system.config.js

This new file is where the configuration of systemjs happens. I found this setup in Dan Wahlin’s Angular2-JumpStart project which can be found here. The only real changes I made from Dan’s file was to adjust the map section to match my folder layout.

(function (global) {

    // map tells the System loader where to look for things
    var map = {
        'app': '../Angular/app', 
        'rxjs': '../Angular/lib/rxjs',
        '@angular': '../Angular/lib/@angular'
    };

    // packages tells the System loader how to load when no filename and/or no extension
    var packages = {
        'app': { main: 'boot.js', defaultExtension: 'js' },
        'rxjs': { defaultExtension: 'js' }
    };

    var packageNames = [
      '@angular/common',
      '@angular/compiler',
      '@angular/core',
      '@angular/http',
      '@angular/platform-browser',
      '@angular/platform-browser-dynamic',
      '@angular/router',
      '@angular/router-deprecated',
      '@angular/testing',
      '@angular/upgrade'
    ];

    // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
    packageNames.forEach(function (pkgName) {
        packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
    });

    var config = {
        map: map,
        packages: packages
    }

    // filterSystemConfig - index.html's chance to modify config before we register it.
    if (global.filterSystemConfig) { global.filterSystemConfig(config); }

    System.config(config);

})(this);

Update Component Imports

With the change in package names all imports that were using angular2 need to be changed to @angular. The following is an example of this from my app.component.ts file.

Before:
import {Component} from 'angular2/core';
import {OnInit} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';

After:
import {Component} from '@angular/core';
import {OnInit} from '@angular/core';
import {HTTP_PROVIDERS} from '@angular/http';

NgFor Change

There was also a slight syntax change around ngFor that changes the name declaration of the current item in the iteration of a loop. The following shows the before and after.

Before:
*ngFor="#contact of contacts"

After:
*ngFor="let contact of contacts"

Complete

With the above changes my application was run able again. The hardest part of the upgrade for me was getting systemjs configured properly. Hope your upgrade goes smooth and if not leave a comment with what issues you had.

Migration from Angular 2 Betas to RC Read More »

Custom Pipes in Angular 2

I am working on a project that is using an ASP.NET Core web API to return JSON that is then used by Angular 2. The dates that needed to be formatted before being shown to the user which lead me to pipes.

Pipes

In Angular 2 pipes are away to apply some transformation on a field before its value is displayed to the user. Some common pipes are provided out of the box for things like numbers, dates and percentages.

For the following example created  is a property for the date a contact was added. To have created just display the month, date and year the date pipe will be used with the short date format.

{{contact.created | date: 'shortDate'}}

The above is standard Angular 2 binding  with an added pipe “|” followed by the name of the pipe which in this case is date. The built-in date pipe can take arguments for how to the date should be formatted. If the created date was today than the resulting output of the above binding would be 4/10/2016. For a full list of built-in formats see the Angular docs.

The Problem

I added the date pipe to the fields that needed formatting and ran the app. Instead of the formatted date I was expecting I got a partially rendered page. A quick peek in Chrome’s dev tools showed the following exception.

EXCEPTION: Invalid argument ‘2016-04-10T08:00:00’ for pipe ‘DatePipe’ in [{{contact.created | date: ‘shortDate’}}

Turns out that the date pipe only works if the value it is processing is a number or a date. I found this out by looking at the code for the date pipe which can be found here. My created property came from JSON which doesn’t have a way to denote something as a date. This means the created property is actually a string instead of a date..

Solution 1 – Convert to a date

One way to fix this issue is to use the string representation of the date to create a new date and assign it over the top of the existing property. For example:

contact.created = new Date(contact.created);

After the above is applied to all the dates that need formatted Angular’s date pipe can be used with no problems.

Solution 2 – Custom pipe

I decided to try writing a custom pipe that would take a string that should be a date and format it if it is actually date using Angular’s date pipe.  The following is the resulting pipe.

import {Pipe, PipeTransform} from 'angular2/core';
import {DatePipe} from 'angular2/common';

@Pipe({ name: 'dateString' })
export class DateString implements PipeTransform {
    transform(value: string, args: any[]): string {
        var parsedDate = Date.parse(value);
        if (isNaN(parsedDate)) {
            return "";
        }
        else {
            return new DatePipe().transform(new Date(parsedDate), args);
        }
    }
}

First Pipe and PipeTransform are imported. The class must be decorated with @Pipe which is also used to give the pipe its name. The class must also implement PipeTransform which defines a transform function.

The transform function is where all the work happens. It takes a value and formatting arguments and return the value that should be displayed. In my case the value is parsed to a date which returns the number of milliseconds since January 1, 1970 00:00:00 UTC or not a number if parsing fails for some reason. For the not a number result an empty string will be return and displayed to the user.

In the case the date is value then a new instance of Angular’s date pipe is created it handles formatting using the new date value which is then return and displayed for the user. In order to use Angular’s date pipe inside my custom pipe it needed to be imported as well.

Custom Pipe Usage

To use a custom pipe it must be imported by the view model class of the view that needs formatted.

import { DateString } from './dateString.pipe';

Then it must be added to the component decorator.

@Component({
    selector: 'viewContacts',
    templateUrl: 'viewContacts.component.html',
    pipes: [DateString]
})

The view will now be able to use the pipe. The syntax is the same as built-in pipes just with the name provided in the pipe decorator which is dateString in this example.

{{contact.created | dateString: 'shortDate'}}

Suggestions

The above are two of the solutions I came up with when I had problems with Angular’s built in date pipe. They are by no means the only options. If you have a suggestion on a better way to handle dates coming from JSON please leave a comment.

Also note that there is an issue logged on the Angular repo to support strings in the built in date pipe which can be found here.

Custom Pipes in Angular 2 Read More »

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 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 »