304

Recently, I have started playing with angular 2. It's awesome so far. So, i have started a demo personal project for the sake of learning using angular-cli.

With the basic routing setup, I now want to navigate to some routes from header, but since my header is a parent to the router-outlet, I receive this error.

app.component.html

<app-header></app-header> // Trying to navigate from this component
    <router-outlet></router-outlet>
<app-footer></app-footer>

header.component.html

<a [routerLink]="['/signin']">Sign in</a>

Now I understand partially I guess that since that component is a wrapper around router-outlet it would not be possible this way to access router. So, is there a possibility to access navigation from outside for a scenario like this?

I would be really happy to add any more information if needed. Thank you in advance.

Update

1- My package.json already has the stable @angular/router 3.3.1 version. 2- In my main app module, I have imported the routing-module. Please see below.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AlertModule  } from 'ng2-bootstrap';
import { LayoutModule } from './layout/layout.module';
import { UsersModule } from './users/users.module';
import { AppRoutingModule } from  './app-routing.module';
import { AppComponent } from './app.component';
import { PageNotFoundComponent } from './shared/components/not-found.component';

@NgModule({
  declarations: [
    AppComponent,
    PageNotFoundComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    AlertModule.forRoot(),
    LayoutModule,
    UsersModule,
    AppRoutingModule  --> This is the routing module. 
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SigninComponent } from './users/signin/signin.component';
import { PageNotFoundComponent } from './shared/components/not-found.component';

const routes: Routes = [
{ path: '**', component: PageNotFoundComponent }
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})

export class AppRoutingModule {}

The route I am trying to access is delegated from another module that is the UsersModule

user-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { SigninComponent } from './signin/signin.component';

const usersRoutes: Routes = [
  { path: 'signin',  component: SigninComponent }
];
@NgModule({
  imports: [
    RouterModule.forChild(usersRoutes)
  ],
  exports: [
    RouterModule
  ]
})

export class UsersRoutingModule { }

While I am trying to navigate from a component that is part of the Layout module, but has no notion of the router module. Is that what is causing the error.

Layout.module.ts

import { NgModule } from '@angular/core';
import { HeaderComponent } from './header/header.component';
import { FooterComponent } from './footer/footer.component';

@NgModule({
  declarations: [HeaderComponent, FooterComponent],
  exports: [HeaderComponent, FooterComponent]
})
export class LayoutModule{}

I am trying to navigate from the HeaderComponent. I would be happy to provide more information if needed.

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
Umair Sarfraz
  • 5,284
  • 4
  • 22
  • 38

16 Answers16

570

You need to add RouterModule to imports of every @NgModule() where components use any component or directive from (in this case routerLink and <router-outlet>.

import {RouterModule} from '@angular/router';
@NgModule({
   declarations:[YourComponents],
   imports:[RouterModule]

declarations: [] is to make components, directives, pipes, known inside the current module.

exports: [] is to make components, directives, pipes, available to importing modules. What is added to declarations only is private to the module. exports makes them public.

See also https://angular.io/api/router/RouterModule#usage-notes

emmby
  • 99,783
  • 65
  • 191
  • 249
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • @Gunter is it ok to import RouterModule multiple times ? For example if I want to use routerLink in a childModule, I need to import RouterModule into the child module whereas it has already been imported by the root app Module... – Olivier Boissé Nov 25 '17 at 16:31
  • Yes, it will only included once into the build output. – Günter Zöchbauer Nov 25 '17 at 16:32
  • Ok but I think we need to take care to call the method `forRoot` only once, the children modules should only import RouterModule without calling the forRoot method – Olivier Boissé Nov 25 '17 at 16:39
  • I think it depends what `forRoot` does. When egistering providers with `forRoot` multiple times, the result is the same as if done only once. If you do other things this might not be different. – Günter Zöchbauer Nov 25 '17 at 16:42
  • 4
    Thanks for this answer! In my case the app worked, but the tests failed. The solution was to import RouterTestingModule in tests, for each component that uses routerLink. – Slavik Shynkarenko Jan 12 '20 at 19:33
  • what about the case where a component is dynamically injected? – albanx Apr 02 '22 at 13:56
  • @albanx Can you provide a StackBlitz example? – Günter Zöchbauer Apr 03 '22 at 07:10
37

You are missing either the inclusion of the route package, or including the router module in your main app module.

Make sure your package.json has this:

"@angular/router": "^3.3.1"

Then in your app.module import the router and configure the routes:

import { RouterModule } from '@angular/router';

imports: [
        RouterModule.forRoot([
            {path: '', component: DashboardComponent},
            {path: 'dashboard', component: DashboardComponent}
        ])
    ],

Update:

Move the AppRoutingModule to be first in the imports:

imports: [
    AppRoutingModule.
    BrowserModule,
    FormsModule,
    HttpModule,
    AlertModule.forRoot(), // What is this?
    LayoutModule,
    UsersModule
  ],
Tanja
  • 41
  • 2
  • 3
  • 11
Ben Richards
  • 3,437
  • 1
  • 14
  • 18
  • This didn't solve the issue. Can you please check my update? – Umair Sarfraz Feb 04 '17 at 12:46
  • @Ben -- "forRoot()" means you're calling a method defined on an imported module that runs configuration or setup for the module. You can also define a method like "forChild()" in a custom module and call it, if you wanted. This method is used for tasks such as setting up a provider for a service. It's also how you get a Singleton Service in Angular. See https://angular.io/guide/singleton-services – RoboBear Dec 27 '18 at 23:53
  • Making AppRoutingModule to be the first in the import solves the problem – aRyhan Sep 30 '20 at 21:50
  • Thanks man moving the RouterModule before FormsModule solves the problem for me – Ravi Khambhati Apr 16 '21 at 19:10
16

I'll add another case where I was getting the same error but just being a dummy. I had added [routerLinkActiveOptions]="{exact: true}" without yet adding routerLinkActive="active".

My incorrect code was

<a class="nav-link active" routerLink="/dashboard" [routerLinkActiveOptions]="{exact: true}">
  Home
</a>

when it should have been

<a class="nav-link active" routerLink="/dashboard" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
  Home
</a>

Without having routerLinkActive, you can't have routerLinkActiveOptions.

cchapman
  • 3,269
  • 10
  • 50
  • 68
13

You need to import RouterModule in your main module.ts file

import {RouterModule} from '@angular/router';


@NgModule({
  imports: [RouterModule],
 )}
Bhargavi
  • 233
  • 3
  • 11
12

I was getting this error, even though I have exported RouterModule from app-routing.module and imported app-routingModule in Root module(app module).

Then I identified, I've imported component in Routing Module only.

Declaring the component in my Root module(App Module) solves the problem.

declarations: [
AppComponent,
NavBarComponent,
HomeComponent,
LoginComponent],
Dharman
  • 30,962
  • 25
  • 85
  • 135
Harshil Parekh
  • 146
  • 1
  • 3
  • 1
    This was my issue, but I did not realize it when I read your response. Is it possible to make it more clear that the app.module.ts needs to add the components where you want to include the link in the declarations portion of the @NgModule – fei0x Feb 23 '22 at 14:15
10

When nothing else works when it should work, restart ng serve. It's sad to find this kind of bugs.

Tudor
  • 2,224
  • 2
  • 21
  • 24
  • 6
    Can conform there is a bug. I just kept deleting the content of the dist folder and rebuilding. Finally it worked. Try adding a link to every component in app.component.ts. If that dosn't work your only option is prayer and fasting. –  Apr 20 '20 at 20:14
  • 1
    Yes restarting ng server was what fixed it for me. After making sure I had RouterModule imported in the module.Thank you @Tudor – Glenster Mar 12 '21 at 07:33
9

Just add RouterModule like this:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SidebarItemComponent } from './sidebar-item/sidebar-item.component';
import { RouterModule } from '@angular/router';

@NgModule({
  declarations: [
    SidebarItemComponent
  ],

  imports: [
    CommonModule,
    RouterModule,
  ], 
})
export class LayoutModule { }
ahmnouira
  • 1,607
  • 13
  • 8
6

I am running tests for my Angular app and encountered error Can't bind to 'routerLink' since it isn't a known property of 'a' as well.

I thought it might be useful to show my Angular dependencies:

    "@angular/animations": "^8.2.14",
    "@angular/common": "^8.2.14",
    "@angular/compiler": "^8.2.14",
    "@angular/core": "^8.2.14",
    "@angular/forms": "^8.2.14",
    "@angular/router": "^8.2.14",

The issue was in my spec file. I compared to another similar component spec file and found that I was missing RouterTestingModule in imports, e.g.

    TestBed.configureTestingModule({
      declarations: [
        ...
      ],
      imports: [ReactiveFormsModule, HttpClientTestingModule, RouterTestingModule],
      providers: [...]
    });
  });
Dharman
  • 30,962
  • 25
  • 85
  • 135
thehme
  • 2,698
  • 4
  • 33
  • 39
4

This problem is because you did not import the module

import {RouterModule} from '@angular/router';

And you must declare this modulce in the import section

   imports:[RouterModule]
NsdHSO
  • 124
  • 7
3

You need to add RouterMoudle into imports sections of the module containing the Header component

Hung Vu
  • 5,624
  • 2
  • 30
  • 27
2

In my case I just need to import my newly created component to RouterModule

{path: 'newPath', component: newComponent}

Then in your app.module import the router and configure the routes:

import { RouterModule } from '@angular/router';

imports: [
        RouterModule.forRoot([
            {path: '', component: DashboardComponent},
            {path: 'dashboard', component: DashboardComponent},
            {path: 'newPath', component: newComponent}
        ])
    ],

Hope this helps to some one !!!

Akitha_MJ
  • 3,882
  • 25
  • 20
2

Just found similar problem in a student's example. After spending 2 hours on checking everything suggested here and in a few similar topics, found that the error was routerlink instead of routerLink.

Seems easy to spot these 'one letter typos', but not in places where you've never saw them before.

2

Old question, and this doesn't appear to be the OP's issue, but I ended up here when searching for the same "Cannot bind to 'routerlink' since it isn't a known property..." message. I thought I'd share what ended up being my issue in case someone else does the same.

After verifying that RouterModule was included in my AppRoutingModule and routes were all set up correctly to no avail, I finally noticed the very subtle issue: Instead of "[routerLink]", I had "[routerlink]" with a lower case 'l'.

Funny how your brain can overlook something staring you in the face sometimes.

Steve In CO
  • 5,746
  • 2
  • 21
  • 32
  • i had the same issue, i was starting to question the whole existence of angular, until i saw this one :)) – PayamB. Mar 11 '23 at 03:47
1

I totally chose another way for this method.

app.component.ts

import { Router } from '@angular/router';
export class AppComponent {

   constructor(
        private router: Router,
    ) {}

    routerComment() {
        this.router.navigateByUrl('/marketing/social/comment');
    }
}

app.component.html

<button (click)="routerComment()">Router Link </button>
Fahimeh Ahmadi
  • 813
  • 8
  • 13
  • 1
    I don't think that's recommended - you will end up with a million click handlers for something that can be automatically handled by Angular routing. – Jeppe Jun 05 '23 at 08:21
0

In the current component's module import RouterModule.

Like:-

import {RouterModule} from '@angular/router';
@NgModule({
   declarations:[YourComponents],
   imports:[RouterModule]

...

It helped me.

Shashikant Pandit
  • 2,752
  • 22
  • 29
-2

I just lost about 2 hours on this. It was a bug of my Visual Studio. I had to reinstall Angular and update my NPM again and now it works again.

Kelvin Schoofs
  • 8,323
  • 1
  • 12
  • 31