4

Trying to create an application with angular2 using angular-cli I'm facing the following problem: I wanted to configure navigation and routing but I get the following error:

Unhandled Promise rejection: Template parse errors: Can't bind to 'routerLink' since it isn't a known property of 'a'. ("s="navbar navbar-fixed-top navbar-custom">

][routerLink]="['/home']">FiT

App structure like this:

app/
  core/
    nav/
      nav.component.ts|html|scss  
      core.module.ts
  home/
    home.component.ts|html|scss
  app-routing.module.ts   
  app.component.ts|html|scss   
  app.module.ts

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 { AppRoutingModule } from './app-routing.module';
import { CoreModule } from './core/core.module';

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    AppRoutingModule,
    CoreModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

core.module.ts:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { NavComponent } from './nav/nav.component';

@NgModule({
  imports: [
    CommonModule // we use ngFor
  ],
  exports: [NavComponent],
  declarations: [NavComponent],
})
export class CoreModule { }

app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { HomeComponent } from './home/home.component';

const routes: Routes = [
  {
    path: '',
    component: HomeComponent
  },
  {
    path: 'home',
    component: HomeComponent
  },
];

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

nav.component.html

<nav class="navbar navbar-fixed-top navbar-custom">
  <div class="container">
    <a class="navbar-brand"  [routerLink]="['/home']">FiT</a>
    <button class="navbar-toggler hidden-md-up" type="button" data-toggle="collapse" data-target="#fit-nav" aria-controls="fit-nav" aria-expanded="false" aria-label="Toggle navigation">
      &#9776;
    </button>
    <div class="collapse navbar-toggleable-sm" id="fit-nav">
      <ul class="nav navbar-nav pull-md-right">
        <li class="nav-item">
          <a class="nav-link">link</a>
        </li>
        <li class="nav-item">
          <a class="nav-link">link</a>
        </li>
        <li class="nav-item">
          <a class="nav-link">Log in</a>
        </li>
        <li class="nav-item">
          <a class="nav-link">sign up</a>
        </li>
      </ul>
    </div>
  </div>
</nav>

So I've tried to dig up an answer and I've seen many similar questions but proposed solutions haven't helped.

Everything looks fine in code. Maybe I'm missing something?

2 Answers 2

3

Directives, components, and pipes are scoped to the module that declares them, unless it imports a module that exports those items. For example

@NgModule({
  declarations: [ SomeComponentThatUsesRouterLink ]
})
class SomeModule {}

@NgModule({
  imports: [
    SomeModule,  <== SomeComponentThatUsesRouterLink can't use routerLink
    RouterModule
  ],
  declarations: [
    AppComponent <== Can use routerLink
  ]
})
class AppModule {}

Here, even though the AppModule imports the RouterModule, it is scoped to only its own declarations, not to SharedModule's, so SomeComponentThatUsesRouterLink can't use the routerLink directive.

Now see here

@NgModule({
  exports: [ RouterModule, CommonModule, FormsModule ]
})
class SharedModule {}

@NgModule({
  imports: [ SharedModule ],
  declarations: [ SomeComponentThatUsesRouterLink ]
})
class SomeModule {}

Now SomeModule can use the RouteModule directives since it imports a module that exports it

Or if you want SomeModule can just import RouterModule itself

@NgModule({
  imports: [ RouterModule ],
  declarations: [ SomeComponentThatUsesRouterLink ]
})
class SomeModule {}

So to fix the problem in your particular case, you need to import the RouterModule into the CoreModule, since the NavComponent needs the router directives

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

Comments

2

You have a syntax error

<a class="navbar-brand"  routerLink="/home">FiT</a>

5 Comments

thank you, Sefa Ümit Oray. It works now. But I've seen in docs that links can have a string path like this: routerLink="..." or we can bind the RouterLink directive to such an array like this: <a [routerLink]="['/heroes']">Heroes</a>. So why the second way doesn't work for me?
@lalexa you need to import RouterModule to your module that imports your nav component in order to use [routerLink] syntax.
@SefaÜmitOray That's not true. You need it even to use the syntax in your answer. But with your syntax, it just won't fail on startup. But the router link doesn't work, as there's no router directive, it's in the RouterModule
@peeskillet What you say it technically true but registering routes requires using RouterModule.forRoot(routes) and importing it in the app module which makes my syntax available app wide.
@SefaÜmitOray But routes are already defined. That's not the problem. forRoot is used so that you get all the routing providers. You don't use that or forChild in modules that don't need to configure routes. If all the module needs is the routing directives, then you just import RouterModule, as it exports all the directives

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.