Exception Angular2: impossible de se lier à 'routerLink' car ce n'est pas une propriété native connue

277

De toute évidence, la version bêta d'Angular2 est plus récente que nouvelle, il n'y a donc pas beaucoup d'informations, mais j'essaie de faire ce que je pense être un routage assez basique.

Le piratage avec le code de démarrage rapide et d'autres extraits du site Web https://angular.io a donné la structure de fichiers suivante:

angular-testapp/
    app/
        app.component.ts
        boot.ts
        routing-test.component.ts
    index.html

Les fichiers étant remplis comme suit:

index.html

<html>

  <head>
    <base href="/">
    <title>Angular 2 QuickStart</title>
    <link href="../css/bootstrap.css" rel="stylesheet">

    <!-- 1. Load libraries -->
    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
    <script src="node_modules/angular2/bundles/router.dev.js"></script>

    <!-- 2. Configure SystemJS -->
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/boot')
            .then(null, console.error.bind(console));
    </script>

  </head>

  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>

</html>

boot.ts

import {bootstrap}    from 'angular2/platform/browser'
import {ROUTER_PROVIDERS} from 'angular2/router';

import {AppComponent} from './app.component'

bootstrap(AppComponent, [
    ROUTER_PROVIDERS
]);

app.component.ts

import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, LocationStrategy, HashLocationStrategy} from 'angular2/router';

import {RoutingTestComponent} from './routing-test.component';

@Component({
    selector: 'my-app',
    template: `
        <h1>Component Router</h1>
        <a [routerLink]="['RoutingTest']">Routing Test</a>
        <router-outlet></router-outlet>
        `
})

@RouteConfig([
    {path:'/routing-test', name: 'RoutingTest', component: RoutingTestComponent, useAsDefault: true},
])

export class AppComponent { }

routing-test.component.ts

import {Component} from 'angular2/core';
import {Router} from 'angular2/router';

@Component({
    template: `
        <h2>Routing Test</h2>
        <p>Interesting stuff goes here!</p>
        `
})
export class RoutingTestComponent { }

La tentative d'exécution de ce code produit l'erreur:

EXCEPTION: Template parse errors:
Can't bind to 'routerLink' since it isn't a known native property ("
        <h1>Component Router</h1>
        <a [ERROR ->][routerLink]="['RoutingTest']">Routing Test</a>
        <router-outlet></router-outlet>
        "): AppComponent@2:11

J'ai trouvé un problème vaguement lié ici; Les directives de liaison de routeur sont brisées après la mise à niveau vers angular2.0.0-beta.0 . Cependant, "l'exemple de travail" dans l'une des réponses est basé sur du code pré-bêta - qui pourrait bien encore fonctionner, mais je voudrais savoir pourquoi le code que j'ai créé ne fonctionne pas.

Tous les pointeurs seraient reçus avec reconnaissance!

Lester Burnham
la source
4
L'autre question a quelque chose de différent: directives: [ROUTER_DIRECTIVES].
Eric Martinez
1
J'obtiens la même erreur même avec ROUTER_DIRECTIVES. @Component({selector: "app"}) @View({templateUrl: "app.html", directives: [ROUTER_DIRECTIVES, RouterLink]})
phil
8
Avec l'ajout directives: [ROUTER_DIRECTIVES]et le passage de [router-link] à [routerLink], je ne reçois plus l'erreur.
phil

Réponses:

392

> = RC.5

importer le RouterModule Voir aussi https://angular.io/guide/router

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

> = RC.2

app.routes.ts

import { provideRouter, RouterConfig } from '@angular/router';

export const routes: RouterConfig = [
  ...
];

export const APP_ROUTER_PROVIDERS = [provideRouter(routes)];

main.ts

import { bootstrap } from '@angular/platform-browser-dynamic';
import { APP_ROUTER_PROVIDERS } from './app.routes';

bootstrap(AppComponent, [APP_ROUTER_PROVIDERS]);

<= RC.1

Votre code est manquant

  @Component({
    ...
    directives: [ROUTER_DIRECTIVES],
    ...)}

Vous ne pouvez pas utiliser des directives comme routerLink ou router-outletsans les faire connaître à votre composant.

Alors que les noms de directive ont été modifiés pour respecter la casse dans Angular2, les éléments utilisent toujours -le nom comme <router-outlet>pour être compatibles avec la spécification des composants Web qui nécessitent un -dans le nom des éléments personnalisés.

s'inscrire dans le monde

Pour rendre ROUTER_DIRECTIVESdisponible globalement, ajoutez ce fournisseur à bootstrap(...):

provide(PLATFORM_DIRECTIVES, {useValue: [ROUTER_DIRECTIVES], multi: true})

alors il n'est plus nécessaire d'ajouter ROUTER_DIRECTIVESà chaque composant.

Günter Zöchbauer
la source
1
oui, vous pouvez également attribuer plusieurs directives au moment de démarrer votre application comme ceci: -provide(PLATFORM_DIRECTIVES, {useValue: [ROUTER_DIRECTIVES, FORM_DIRECTIVES, ETC...], multi: true})
Pardeep Jain
1
C'est vrai, mais ils FORM_DIRECTIVESsont déjà inclus PLATFORM_DIRECTIVESpar défaut.
Günter Zöchbauer
2
C'était super, merci. J'ai également trouvé cela utile lorsque j'essayais de tout rassembler: stackoverflow.com/questions/34391790/…
Jeff
Peut-être une question stupide ici, mais qu'est-ce que RC.1, RC.2 ici? J'utilise angulaire 2.1.2, quel RC est-ce?
Jian Chen
1
@AlexanderMills pourquoi les vieux andwers vous font peur? Les anciennes réponses sont testées au combat et sont donc très fiables; p
Günter Zöchbauer
116

Pour les personnes qui trouvent cela en tentant d'exécuter des tests parce que via npm testou en ng testutilisant Karma ou autre chose. Votre module .spec a besoin d'un import de test de routeur spécial pour pouvoir être construit.

import { RouterTestingModule } from '@angular/router/testing';

TestBed.configureTestingModule({
    imports: [RouterTestingModule],
    declarations: [AppComponent],
});

http://www.kirjai.com/ng2-component-testing-routerlink-routeroutlet/

rayepps
la source
2
C'est une bonne prise! Mon projet ne rencontrait aucun problème de fonctionnement normal, c'était dans le specfichier que je devais l'ajouter. Merci @raykrow!
kbpontius
1
Confirmé de fonctionner également en angulaire 4. Merci pour cela!
JCisar
Ce doit être la réponse acceptée, la réponse acceptée est fausse, car lors de l'importation RouterModule, alors vous devez appeler forRootpour satisfaire le module et ensuite vous devez fournir le BASE_HREFet ...
Milad
1
Avez-vous une idée si c'est différent pour Angular 5+? J'obtiens l'erreur similaire Can't bind to 'active' since it isn't a known property of 'a'.dans plusieurs de mes tests unitaires et j'ai importé RouterTestingModule.
Stuart Updegrave
25

Avertissement lors du codage avec Visual Studio (2013)

J'ai perdu 4 à 5 heures à essayer de déboguer cette erreur. J'ai essayé toutes les solutions que j'ai trouvées sur StackOverflow par la lettre et j'ai toujours cette erreur:Can't bind to 'routerlink' since it isn't a known native property

Sachez que Visual Studio a la mauvaise habitude de mettre automatiquement en forme du texte lorsque vous copiez / collez du code. J'ai toujours obtenu un petit ajustement instantané de VS13 (l'étui camel disparaît).

Ce:

<div>
    <a [routerLink]="['/catalog']">Catalog</a>
    <a [routerLink]="['/summary']">Summary</a>
</div>

Devient:

<div>
    <a [routerlink]="['/catalog']">Catalog</a>
    <a [routerlink]="['/summary']">Summary</a>
</div>

C'est une petite différence, mais suffisante pour déclencher l'erreur. La partie la plus laide est que cette petite différence a continué à éviter mon attention à chaque fois que je copiais et collais. Par pur hasard, j'ai vu cette petite différence et l'ai résolue.

Adrian Moisa
la source
4
Merci, vous auriez pu mentionner la différence entre "routerlink" et "routerLink". Angular 2 s'attend à ce que "routerLink" soit présent mais trouve "routerlink"
Narendran Solai Sridharan
Merci, pour une raison quelconque, un didacticiel utilisé "routeur-lien" avec un tiret entre les deux. Mais routerLink est la bonne version.
windmaomao
La même chose se produit avec webpack et html-minifier, mais uniquement en production. add caseSensitive: true to the html-loader options see: github.com/SamanthaAdrichem/webpack-3.9.1-splitted-config-an‌ gular for a working angular 5 + webpack 3.9 config
Samantha Adrichem
12

Pour> = V5

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

const appRoutes: Routes = [
  {path:'routing-test', component: RoutingTestComponent}
];

@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
    // other imports here
  ]
})

composant:

@Component({
    selector: 'my-app',
    template: `
        <h1>Component Router</h1>
        <a routerLink="/routing-test" routerLinkActive="active">Routing Test</a>
        <router-outlet></router-outlet>
        `
})

Pour <V5

Peut également être utilisé RouterLinkcomme un directivesie. directives: [RouterLink]. qui a fonctionné pour moi

import {Router, RouteParams, RouterLink} from 'angular2/router';

@Component({
    selector: 'my-app',
    directives: [RouterLink],
    template: `
        <h1>Component Router</h1>
        <a [routerLink]="['RoutingTest']">Routing Test</a>
        <router-outlet></router-outlet>
        `
})

@RouteConfig([
    {path:'/routing-test', name: 'RoutingTest', component: RoutingTestComponent, useAsDefault: true},
])
Shaishab Roy
la source
Je ne pense pas que cela s'applique plus (Angular 5) etc.
Alexander Mills
10

En général, chaque fois que vous obtenez une erreur comme Can't bind to 'xxx' since it isn't a known native property, la cause la plus probable est d'oublier de spécifier un composant ou une directive (ou une constante qui contient le composant ou la directive) dans le directivestableau de métadonnées. Tel est le cas ici.

Puisque vous n'avez pas spécifié RouterLinkni la constante ROUTER_DIRECTIVES- qui contient les éléments suivants :

export const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, 
  RouterLinkActive];

- dans le directivestableau, puis lorsque l'analyse angulaire

<a [routerLink]="['RoutingTest']">Routing Test</a>

il ne connaît pas la directive RouterLink (qui utilise le sélecteur d' attributrouterLink ). Étant donné qu'Angular sait ce qu'est l' aélément, il suppose qu'il [routerLink]="..."s'agit d'une liaison de propriété pour l' aélément. Mais il découvre alors que ce routerLinkn'est pas une propriété native des aéléments, d'où il lève l'exception concernant la propriété inconnue.


Je n'ai jamais vraiment aimé l' ambiguïté de la syntaxe . C'est à dire, considérez

<something [whatIsThis]="..." ...>

Rien qu'en regardant le HTML, on ne sait pas si whatIsThisc'est

  • une propriété native de something
  • sélecteur d'attribut d'une directive
  • une propriété d'entrée de something

Nous devons savoir lesquelles directives: [...]sont spécifiées dans les métadonnées du composant / directive afin d'interpréter mentalement le HTML. Et lorsque nous oublions de mettre quelque chose dans le directivestableau, je pense que cette ambiguïté rend le débogage un peu plus difficile.

Mark Rajcok
la source
7

Vous avez dans votre module

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

vous devez exporter le module RouteModule

exemple:

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

pour pouvoir accéder aux fonctionnalités pour tous ceux qui importent ce module.

alehn96
la source
5

J'ai essayé toutes les méthodes mentionnées ci-dessus, mais aucune méthode ne fonctionne pour moi.Enfin, j'ai obtenu une solution pour le problème ci-dessus et cela fonctionne pour moi.

J'ai essayé cette méthode:

En Html:

<li><a (click)= "aboutPageLoad()"  routerLinkActive="active">About</a></li>

Dans le fichier TS:

aboutPageLoad() {
    this.router.navigate(['/about']);
}
Sunil Kumar KK
la source
4

Dans mon cas, j'ai importé le module RouterModule in App mais pas importé dans mon module de fonctionnalités. Après l'importation du module routeur dans mon EventModule, l'erreur disparaît.

import {NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {EventListComponent} from './EventList.Component';
import {EventThumbnailComponent} from './EventThumbnail.Component';
import { EventService } from './shared/Event.Service'
import {ToastrService} from '../shared/toastr.service';
import {EventDetailsComponent} from './event-details/event.details.component';
import { RouterModule } from "@angular/router";
@NgModule({
  imports:[BrowserModule,RouterModule],
  declarations:[EventThumbnailComponent,EventListComponent,EventDetailsComponent],
  exports: [EventThumbnailComponent,EventListComponent,EventDetailsComponent],
   providers: [EventService,ToastrService]
})
export class EventModule {

 }
Code-EZ
la source
3

Si vous obtenez cette erreur pendant les tests unitaires, veuillez écrire ceci.

import { RouterTestingModule } from '@angular/router/testing';
beforeEach(async(() => {
  TestBed.configureTestingModule({
   imports: [RouterTestingModule],
   declarations: [AppComponent],
 });
}));
Deeksha Bilochi
la source
0

J'apprécie vraiment la réponse de @ raykrow quand on a ce problème uniquement dans un fichier de test! C'est là que je l'ai rencontré.

Comme il est souvent utile d'avoir une autre façon de faire quelque chose en tant que sauvegarde, je voulais mentionner cette technique qui fonctionne également (au lieu d'importer RouterTestingModule):

import { MockComponent } from 'ng2-mock-component';
. . .
TestBed.configureTestingModule({
  declarations: [
    MockComponent({
      selector: 'a',
      inputs: [ 'routerLink', 'routerLinkActiveOptions' ]
    }),
    . . .
  ]

(En règle générale, on utiliserait routerLinkun <a>élément mais ajusterait le sélecteur en conséquence pour les autres composants.)

La deuxième raison pour laquelle je voulais mentionner cette solution alternative est que, même si elle m'a bien servi dans un certain nombre de fichiers de spécifications, j'ai rencontré un problème avec elle dans un cas:

Error: Template parse errors:
    More than one component matched on this element.
    Make sure that only one component's selector can match a given element.
    Conflicting components: ButtonComponent,Mock

Je ne pouvais pas vraiment comprendre comment cette maquette et la mienne ButtonComponentutilisaient le même sélecteur, alors la recherche d'une autre approche m'a conduit ici à la solution de @ raykrow.

Michael Sorens
la source
0

Si vous utilisez des modules partagés, ajoutez simplement RouterModule à un module où votre composant est déclaré et n'oubliez pas d'ajouter <router-outlet></router-outlet>

Référencé à partir d'ici RouterLink ne fonctionne pas

Yevheniy Potupa
la source
-4

Ma solution est simple. J'utilise [href] au lieu de [routerLink]. J'ai essayé toutes les solutions pour [routerLink]. Aucun d'eux ne fonctionne dans mon cas.

Voici ma solution:

<a [href]="getPlanUrl()" target="_blank">My Plan Name</a>

Écrivez ensuite la getPlanUrlfonction dans le fichier TS.

G Chen
la source