Angular 5.0 released

Home / Angular 5.0 released

Yesterday, Angular 5.0 was released. The Angular team provides a handy upgrade guide to help with upgrading from any previous version of Angular. Upgrading from 4.x was pretty straight-forward.


The announcement from yesterday is here:

https://blog.angular.io/version-5-0-0-of-angular-now-available-37e414935ced

The handy upgrade guide is here:

https://angular-update-guide.firebaseapp.com/

For my testing, I used my previous Angular 4.x Visual Studio solution to try out migrating.

Of course, the first step was to point all of my references in my package.json, as seen in the screen shot, to use the 5.0.0 versions of Angular.

One thing that caught my attention, though, was the suggestion to now use HttpClient and HttpClientModule rather than the Http module. In my demo code, I was replacing the Http service/module with my own implementation to simulate having an Http interceptor. I would intercept each request and display a modal/blocking wait-indicator. A few things have changed since I wrote that bit of code. Specifically, since then, there is now a proper HttpInterceptor in Angular. Using this class, I rewrote my “modal spin” service to implement the HttpInterceptor.

The newer Angular HttpInterceptor class only has a single “intercept” method. This makes it considerably cleaner than my previous implementation. I had already written my own “SpinService” that utilizes Spin.js to display a CSS-only spinner/modal. With that in mind, a basic interceptor looks like this:

@Injectable()
export class SpinInterceptor implements HttpInterceptor {
    public pendingRequests: number = 0;
    public showLoading: Boolean = false;

    constructor(private spinSvc: SpinService) { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.pendingRequests++;
        this.turnOnModal();

        return next.handle(req)
            .do((event: HttpEvent<any>) => {
                if (event instanceof HttpResponse) {

                }
            })
            .catch(err => {
                if (err instanceof HttpErrorResponse) {
                    if (err.status === 401) {
                        // JWT expired, go to login
                        // Observable.throw(err);
                    }
                }

                console.log('Caught error', err);
                return Observable.throw(err);
            })
            .finally(() => {
                console.log("Finally.. delaying, though.")
                var timer = Observable.timer(1000);
                timer.subscribe(t => {
                    this.turnOffModal();
                });
            });
    }

    private turnOnModal() {
        if (!this.showLoading) {
            this.showLoading = true;
            this.spinSvc.spin("body", "modal", "#FFFFFF", "rgba(51, 51, 51, 0.1)");
            console.log("Turned on modal");
        }
        this.showLoading = true;
    }

    private turnOffModal() {
        this.pendingRequests--;
        if (this.pendingRequests <= 0) {
            if (this.showLoading) {
                this.spinSvc.spin("body", "modal", "#FFFFFF", "rgba(51, 51, 51, 0.1)");
            }
            this.showLoading = false;
        }
        console.log("Turned off modal");
    }
}

And then, in our app module, we only have to have to specify that we are providing an HttpInterceptor in our list of providers:

{ provide: HTTP_INTERCEPTORS, useClass: SpinInterceptor, multi: true },

Beyond that slightly involved change, the upgrade from 4.x to 5.x was painless.

The latest demo project I have running 5.x is available on github here:

https://github.com/long2know/angular-core-demo

EDIT: One other thing I found that must be updated is “ngtools/webpack” in order to replace AotPlugin with AngularCompilerPlugin. Otherwise, builds, for example, in Azure will fail when packing with webpack. This issue was mentioned on github. The error you might get looks like this:

EXEC : ERROR in error : Please update @angular/cli. Angular 5+ requires at least Angular CLI 1.5+ [D:\home\site\repository\aspnet-core-demo\aspnet-core-demo.csproj]
          at throwNotSupportedError (D:\home\site\repository\aspnet-core-demo\packages\compiler-cli\src\ngtools_api.ts:132:9)
          at Function.NgTools_InternalApi_NG_2.codeGen (D:\home\site\repository\aspnet-core-demo\packages\compiler-cli\src\ngtools_api.ts:80:11)
          at _donePromise.Promise.resolve.then (D:\home\site\repository\aspnet-core-demo\node_modules\@ngtools\webpack\src\plugin.js:386:44)
          at process._tickCallback (internal/process/next_tick.js:103:7)
          at Module.runMain (module.js:606:11)
          at run (bootstrap_node.js:394:7)
          at startup (bootstrap_node.js:149:9)
          at bootstrap_node.js:509:3
D:\home\site\repository\aspnet-core-demo\aspnet-core-demo.csproj(49,5): error MSB3073: The command "node node_modules/webpack/bin/webpack.js --env.prod" exited with code 2.

I updated my package.json like so:

"@ngtools/webpack": "1.8.0"

And then, in my webpack.config.js, I replaced references to the AotPlugin like so:

const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin;

.... and then in plugins defn ...

// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin(),
new AngularCompilerPlugin({
	tsConfigPath: './tsconfig.json',
	entryModule: path.join(__dirname, 'ClientApp/app/app.module#AppModule')
})

Leave a Reply