Wednesday, July 6, 2016

Angular 2...

I'm grinding my way through Angular 2 and I keep hitting some bumps along the way.
I've been trying to create a dashboard app for my company that I can quickly spin up forms and data. The hope was with Angular 2 and JavaScript I could accomplish this faster than a .net application. I wrote a medium sized application in Angular 1 at the beginning of the year and it went very well. For the back-end services I changed from a monolithic service gateway to more of a microservices using Service Stack api. I can now spin up a quick database and connection in a hour or so with a RESTful api. With the front end I wanted to do something similar so for the past month I've been working on the previously mentioned dashboard. I started with RC 1. Since it was new to me, I didn't miss out on some of the breaking changes and I knew routing and forms would be changed in the coming months/weeks. As I messed around with some newbie projects while I was implementing my microservices and other tasks RC 2 came out. Everything became a learning curve and it took me a bit to get back up to speed. I downloaded a dashboard templateAkveo admin 2 desktop and shortly thereafter RC 3 came out and then last week RC 4 was released. Routing, Forms, and other changes/bug fixes and learning how to implement the dashboard set me back a bit. I created my own local git repository and set off to updating the routing to the beta router. I didn't have time for akveo to update it and I wanted to stay with the Angular team as they released the product. I also had to learn about form builder (akveo did implement this..). The problem with the forms and binding is there are multiple ways to do this and lots of opinions and examples to choose from.
Since I was implementing authentication I picked one and was wondering how to force each page to be required to authenticate and low and behold auth.gaurd came to the rescue:
@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private authService: AuthService, private router: Router){}

    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot
    ) 
    {   
        let user = localStorage.getItem('user');
         if (user === null)
        {
            this.router.navigate(['/login']);
            return false;    
        }
        return true;
    }
}
Simple but effective for the time being. Okay I got that all working and needed to actually get a user object from the service once the user was authenticated. Well, now I get to dive into the world of observables. In reality, there isn't that much difference, but Angular 2 team almost makes it more difficult on how to decide on what to use. Promise or Observable with other variations on observable. For example if you have Pluralsight watch the John Papa and Ward Bell play by play video and they discuss all the different ways in which they could be used in different situations. If you want to look at the code he has examples of both in the component and service. Now back to getting the user data from the service before render. I couldn't figure out how to populate the object before render in which it would be undefined. Here is how I accomplished it: Here is one of my routerConfig ts files:
export const PagesRoutes: RouterConfig = [
     { path: '', redirectTo: '/pages', terminal: true },
      { path: 'pages',
            component: Pages,
            resolve: {
                  teamMember: MemberResolver
            },
            canActivate: [AuthGuard],
            children: [
                  {
                        path: '',
                        component: Dashboard,
                        canActivate: [AuthGuard]
                  },
                  {
                        path: 'Dashboard',
                        component: Dashboard,
                        canActivate: [AuthGuard]
                  },
                  {
                        path: 'Charts',
                        component: Charts,
                        canActivate: [AuthGuard],
                        children:
                        [
                              {
                              path: 'ChartistJs',
                              component: ChartistJs,
                              canActivate: [AuthGuard]
                              }
                        ]
                  }
            ]
      }
];
Notice the resolve in the pages component. It uses the resolver from the router and you create a class like this:
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { TeamMember, TeamMemberService } from './index';
import { Observable } from 'rxjs/Rx';
import { Injectable } from '@angular/core';

@Injectable()
export class MemberResolver implements Resolve {
      constructor(private _teamMemberService : TeamMemberService) {}
      _teamMember: TeamMember;
      resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable {
            let userName = localStorage.getItem('user');
           return this._teamMemberService.callService_RxObservable(userName);
                
      }
}
And now to retrieve the observable data:
export class Pages implements OnInit {
 
  constructor(private route: ActivatedRoute, private _teamMemberService: TeamMemberService) {
  }
   ngOnInit() {
    
     this._teamMemberService.teamMember = this.route.snapshot.data['teamMember'];
     
   }
}
The ink on the Resolve documentation on angular.io still wasn't dry when I discovered this. It took me a bit to understand it and I was using the activatedRoute along with the snapshot to retrieve the observable data.