0
votes

In angular 2 the RouterOutlet seems to have changed with the new library for @router does anyone know what to?

I'm using angular 2 with typescript.

My code below redirects the user to home view if they are not logged in when trying to reach a page that requires login.

Since I've updated my library for @angular/router. it seems to stop working and the console doesnt give me a readable message but I'm assuming the RouterOutlet has changed or the ComponentInstruction.

These are my angular2 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",

I've added my code below:

import {Directive, Attribute, ElementRef, DynamicComponentLoader} from '@angular2/core'; import {Router, RouterOutlet, ComponentInstruction} from '@angular2/router';

import {Environment} from './models/environment/environment';

@Directive({
  selector: 'router-outlet'
})

export class LoggedInRouterOutlet extends RouterOutlet {
  publicRoutes: any;
  private parentRouter: Router;
  environment: Environment;

  constructor(_elementRef: ElementRef, _loader: DynamicComponentLoader, _parentRouter: Router, @Attribute('name') nameAttr: string, _environment: Environment) {
    super(_elementRef, _loader, _parentRouter, nameAttr);

    this.parentRouter = _parentRouter;
    this.environment = _environment;

    this.publicRoutes = [
      'home',
      'contact',
      'forgotpassword',
      'socialRegister',
      'login',
      'register/',
      'register/:id',
      'blog/:slug',
      'blog',
      'sitemap',
      'newJobs',
      'newJob/:slug'
    ];
  }

  activate(instruction: ComponentInstruction) { 
     var ref = new Firebase(this.environment.firebaseUrl);

     var authToken = ref.getAuth();  
     var isPublicRoute = this.publicRoutes.indexOf(instruction.urlPath) > -1;
     var registerRouter = instruction.urlPath.substring(0, 8) === "register";
     var socialRegister = instruction.urlPath.substring(0, 14) === "socialRegister";
     var blogRouter = instruction.urlPath.substring(0, 4) === "blog";
     var newJobRouter = instruction.urlPath.substring(0, 6) === "newJob";

     if(authToken == null && !isPublicRoute && !registerRouter && !socialRegister && !blogRouter && !newJobRouter)
        this.parentRouter.navigate(['/Home']);

     return super.activate(instruction); 
  }

}
1
So basically I cannot extend RouterOutlet like in router-deprecated? - AngularM
Overall, what I'm trying to achieve is to detect the route name in a global place in my code and redirect the user before it hits the component. In the past it would hit the component and cause all types of errors. - AngularM
Currently not. You should stay away from @angular/router anyway. It will be replaced soon (again). Rather stick with @angular/router-deprecated. - Günter Zöchbauer
hmm I have no choice at the moment - AngularM

1 Answers

1
votes

This is what I have so far:

my-app.component.ts

import { Component } from '@angular/core';
import { MeComponent } from './+me';
import { Routes , Router, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from '@angular/router';
import { LoggedInRouterOutlet } from './utilities/loggedinoutlet.directive';
import { LoginComponent } from './+login';

@Component({
  moduleId: module.id,
  selector: 'my-app-app',
  templateUrl: 'my-app.component.html',
  styleUrls: ['my-app.component.css'],
  directives: [LoggedInRouterOutlet],
  providers: [ROUTER_PROVIDERS]
})
@Routes([
  {path: '/me', component: MeComponent},
  {path: '/login', component: LoginComponent}
])
export class MyAppAppComponent {

  constructor(private router: Router){};

  title = 'my-app works!';

}

loggedinrouter.directive.ts

import { Directive, Attribute, ResolvedReflectiveProvider, ViewContainerRef, ComponentRef, ComponentFactory } from '@angular/core';
import { Router, RouterOutletMap } from '@angular/router'
import { RouterOutlet } from '@angular/router/src/directives/router_outlet';

@Directive({
  selector: 'router-outlet'
})
export class LoggedInRouterOutlet extends RouterOutlet{
  publicRoutes: any;

  constructor(routerOutletMap: RouterOutletMap, _location: ViewContainerRef, name: string) {
    super(routerOutletMap, _location, name);

    // The Boolean following each route below 
    // denotes whether the route requires authentication to view
    this.publicRoutes = {
      'login': true,
      'signup': true
    };
  }

  load(factory: ComponentFactory<any>, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap) {
    // DO AUTH CHECK HERE

    return super.load(factory, providers, outletMap);
  }

}

The problem I'm having is that since name is not an acceptable attribute for the @Routes decorator path objects, I can't get the path or name of the route that's calling the RouterOutlet.