2

I want to provide a constant in my application basing on QueryParam from url.

localhost:4200?flag=true

In my module providers I added

{ provide: FLAG, useFactory: FlagFactory, deps: [...] }

So I am interested if there is a way how to do it without parsing url manually

function FlagFactory() {
  return location.search.includes('flag');
}
mgrinko
  • 515
  • 1
  • 4
  • 13

2 Answers2

1

What about using Angular Router?

The router tracks query parameters, so they should be available on you initial route '/'

your root component could have a route that allows this

constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.sub = this.route.params.subscribe(params => {
       this.flag = params['flag']; 

    });
  }
Dean Chalk
  • 20,076
  • 6
  • 59
  • 90
  • Because your code will work only inside a component. But before opening any component I need to check if the user may open it. – mgrinko Aug 03 '17 at 05:54
  • So I am sending request to API from guards. And these requests require additional Header to be sent. Thats why I extended Http and BaseRequestOptions and added required Headers to each request. I am injecting the flag there. – mgrinko Aug 03 '17 at 06:00
  • do it in your root component (typically app.component) which you'll want to load before making any decisions about users etc – Dean Chalk Aug 03 '17 at 06:01
  • route params are empty in root component so it is not the case – mgrinko Aug 03 '17 at 09:05
1

I was able to do this by using Angular's resolve. Resolve allows you to access the route and query params BEFORE your route component is loaded.

In your case, I would create a resolver class that looks something like this:

@Injectable()
export class FlagRouteResolver implements Resolve<any> {
    constructor(private flagService: FlagService) {}

    resolve(route: ActivatedRouteSnapshot) {
        this.flagService.isFlagged = route.queryParamMap.get('flag');

        // Need to return an observable for all resolve() methods
        return Observable.of(null);
    }
}

And your AppModule should look something like this:

@NgModule({
    imports: [
        RouterModule.forRoot([{
            path: 'flagRoute',
            component: FlagComponent,
            resolve: { test: FlagRouteResolver }
        }]),
    ],
    providers: [
        FlagService,
        FlagRouteResolver
    ],
    declarations: [
        FlagComponent
    ]
})

So now, within your route component, you should be able to access that value immediately in the constructor like so:

constructor(private flagService: FlagService) {
    this.isFlagged = this.flagService.isFlagged;
}

But if you'd still like to inject it, you can also do it like so:

providers: [{
    provide: FLAG,
    useFactory: (flagService: FlagService) => {
        return this.flagService.isFlagged;
    },
    deps: [FlagService]
}]
Lani
  • 1,224
  • 1
  • 9
  • 15