24

I have created a single page mortgage calculator application in Angular 2, which acts like a learning playground for me (trying to get more accustomed to technology stack currently used at work)... It's running at http://www.mortgagecalculator123.com if you want to look at it. I've made it open source with a Fork Me link right on the page if you want to look at it.

Anyhow, what I want to do, is to be able to pass variables to my app, straight from the URL, so they can be consumed by my Angular 2 app. Something like this: http://www.mortgagecalculator123.com/?var1=ABC&var2=DEF

I've tried following, in my app.component.ts, I've added following:

import { Router, ActivatedRoute, Params } from '@angular/router';

AppComponent {
private var1: string;
private var2: string;

constructor(
  private route: ActivatedRoute,
  private router: Router
  ) {}

ngOnInit() {
  this.route.params.forEach((params: Params) => {
      this.var1 = params['var1'];
      this.var2 = params['var2'];
  });

  console.log(this.var1, this.var2);
}
...
}

But this won't work, when I run npm start, I get following error:

aot/app/app.component.ngfactory.ts(45,30): error TS2346: Supplied parameters do not match any signature of call target.

enter image description here

2 Answers 2

58
+50

I created a pull request with the query params working. I will try to explain everything I did.

The reason why the previous answers doesn't work is because you aren't using the router at all. You created a massive app component without routes. To fix that we need to start using the route module, I also advise you to read these two tutorials: Routing and Routing & Navigation.

First we need to change your index.html, add this to your <head>:

<base href="/">

See here why it's important to add that.

Then since you are using your AppComponent to show everything we need to create a new component, which we will call RootComponent. On your index.html change <my-app> to <root>; it will look like this:

<root>Loading...</root>

Now inside your app folder we need to create two files the first one will be root.component.ts which will look like this:

import { Component } from '@angular/core';

@Component({
  selector: 'root',
  template: `<router-outlet></router-outlet>`,
})
export class RootComponent {
  constructor() {  }
}

Look that we have the <router-outlet></router-outlet> as a template, Angular will inject our components based on the route.

We still need to create one more file, which will be main.route.ts, this is what it looks like:

import { Routes, RouterModule }   from '@angular/router';
import { AppComponent } from './app.component';

export const mainRoutes: Routes = [
  { path: '', component: AppComponent }
];
export const mainRoutingProviders: any[] = [];
export const routing = RouterModule.forRoot(mainRoutes);

In this file we are saying that for our base route, we want to render our AppComponent

We have created our new files, now we need to tell our App Module about them, in your app.module.ts so we import the new files and declare the new component. We also need to change our boostrap component:

import {NgModule}      from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {AppComponent}  from './app.component';
import {RootComponent}  from './root.component'; // we import our new RootComponent
import {ChartModule} from 'primeng/primeng';
import {TooltipModule} from 'primeng/primeng';
import { routing, mainRoutingProviders } from './main.routes'; // We also import our Routes

@NgModule({
  imports: [
    BrowserModule,
    ChartModule,
    FormsModule,
    mainRoutingProviders, // we also need to import our route provider into the module
    ReactiveFormsModule,
    routing, // and also import our routes declarations
    TooltipModule
  ],
  declarations: [AppComponent, RootComponent], // we declare our new RootCpmponent
  bootstrap: [RootComponent] // Notice that we are now using our RootComponent to bootstrap our app
})
export class AppModule {
}

Now with all this in place we can now finally start passing parameters to our app, on your AppComponent import the Router, ActivatedRoute and the Params from @angular/router so your AppComponent will look something like this:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

export class AppComponent implements OnInit, OnDestroy {
  private var1: string;
  private var2: string;
  private sub: Subscription;

  constructor(
    private route: ActivatedRoute,
    private router: Router
  ) {}

  ngOnInit() {
    // assign the subscription to a variable so we can unsubscribe to prevent memory leaks
    this.sub = this.route.queryParams.subscribe((params: Params) => {
      this.var1 = params['var1'];
      this.var2 = params['var2'];
      console.log(this.var1, this.var2);
    });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }
...
}

You can see the pull request here

Sign up to request clarification or add additional context in comments.

13 Comments

Fabio, this is exactly what I was trying to figure out the entire time. Thank you so much. I am still a newbie when it comes to Angular 2, so thanks a lot for spending your valuable time to explain everything. Not only it works now, but it has been a great learning exercise following the logic you've outlined. Well deserved 50 points for reputation.
One more question.... in app.component.ts, is there a need to keep: 'private router: Router', on line 65? Looks like that's an unused parameter no?
true, you don't need that. Unless you eventually plan to redirect to some route.
Solved, thanks. The problem was that I was defining a Route with path: '' redirecting to my component which has path mycomponent. If I launch http:\\myapp\?myVar=AAA I do not get any variable. But if I launch http:\\myapp\mycomponent?myVar=AAA I am able to retrieve the parameter from the url.
This was very helpful. Note that Angular discourages the use of queryParams, you should use queryParamMap instead. You can access the parameters with params['params']['var1'] angular.io/guide/router#activated-route
|
2

It seems you are dealing with Queryparams . So to access them, you can try below code,

this.var1= this.route
      .queryParams
      .map(params => params['var1']);

4 Comments

When I do that, I get following errors: aot/app/app.component.ngfactory.ts(45,30): error TS2346: Supplied parameters do not match any signature of call target. app/app.component.ts(90,39): error TS2339: Property 'map' does not exist on type 'Observable<{ [key: string]: any; }>'.
I've tried to use: import 'rxjs/add/operator/map'; but then I am back to original error TS2346: Supplied parameters do not match any signature of call target. Crazy how something simple as passing vars can be so complicated...
Thanks for trying, hopefully someone else can help.
FYI, queryParams has been replaced w/ queryParamsMap. Source

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.