Exceção Angular2: Não é possível vincular ao 'routerLink', pois não é uma propriedade nativa conhecida


277

Obviamente, a versão beta do Angular2 é mais nova que a nova, então não há muita informação por aí, mas estou tentando fazer o que acho que é um roteamento bastante básico.

A invasão com o código de início rápido e outros trechos do site https://angular.io resultou na seguinte estrutura de arquivo:

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

Com os arquivos sendo preenchidos da seguinte maneira:

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 { }

Tentar executar este código produz o erro:

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

Encontrei um problema vagamente relacionado aqui; Diretivas de link de roteador quebradas após a atualização para angular2.0.0-beta.0 . No entanto, o "exemplo de trabalho" em uma das respostas é baseado no código pré-beta - que ainda pode funcionar, mas eu gostaria de saber por que o código que criei não está funcionando.

Qualquer ponteiro seria recebido com gratidão!


4
A outra questão tem algo diferente: directives: [ROUTER_DIRECTIVES].
Eric Martinez

1
Estou recebendo o mesmo erro, mesmo com ROUTER_DIRECTIVES. @Component({selector: "app"}) @View({templateUrl: "app.html", directives: [ROUTER_DIRECTIVES, RouterLink]})
phil

8
Com a adição directives: [ROUTER_DIRECTIVES]e a alteração de [router-link] para [routerLink], não estou mais recebendo o erro.
phil

Respostas:


392

> = RC.5

importe o RouterModule Consulte também 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

Seu código está ausente

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

Você não pode usar diretivas como routerLinkou router-outletsem divulgá-las ao seu componente.

Embora os nomes das diretivas tenham sido alterados para fazer distinção entre maiúsculas e minúsculas no Angular2, os elementos ainda usam -o nome como <router-outlet>compatíveis com as especificações de componentes da web que requerem a -no nome de elementos personalizados.

registrar globalmente

Para disponibilizar ROUTER_DIRECTIVESglobalmente, adicione este provedor a bootstrap(...):

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

não é mais necessário adicionar ROUTER_DIRECTIVESa cada componente.


1
sim, você pode atribuir várias directivas também no momento da bootstraping seu aplicativo como este: -provide(PLATFORM_DIRECTIVES, {useValue: [ROUTER_DIRECTIVES, FORM_DIRECTIVES, ETC...], multi: true})
Pardeep Jain

1
Isso mesmo, mas já FORM_DIRECTIVESestão incluídos PLATFORM_DIRECTIVESpor padrão.
Günter Zöchbauer

2
Isso foi ótimo, obrigado. Eu também encontrei este útil quando se tenta colocar tudo junto: stackoverflow.com/questions/34391790/...
Jeff

Talvez uma pergunta estúpida aqui, mas o que é RC.1, RC.2 aqui? Estou usando o angular 2.1.2, qual é o RC?
Jian Chen #

1
@AlexanderMills Por que os velhos andwers te assustam? Respostas antigas são testadas em batalha e, portanto, muito confiáveis; p
Günter Zöchbauer

116

Para pessoas que encontram isso ao tentar executar testes porque via npm testou ng testusam o Karma ou qualquer outra coisa. Seu módulo .spec precisa de uma importação especial de teste de roteador para poder construir.

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

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

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


2
Esta é uma ótima captura! Meu projeto não estava tendo nenhum problema com a operação normal, era no specarquivo que eu tinha que adicionar isso. Obrigado @raykrow!
Kbpontius

1
Confirmado para trabalhar também na angular 4. Obrigado por isso!
JCisar #

Esta deve ser a resposta aceita, a resposta aceita é errado, porque ao importar RouterModule, então você precisa chamar forRootpara satisfazer o módulo e, em seguida, você deve fornecer o BASE_HREFe ...
Milad

1
Você tem alguma idéia se isso é diferente para o Angular 5+? Estou recebendo o erro semelhante Can't bind to 'active' since it isn't a known property of 'a'.em vários dos meus testes de unidade e importado RouterTestingModule.
Stuart Updegrave

25

Palavra de cautela ao codificar com o Visual Studio (2013)

Eu perdi 4 a 5 horas tentando depurar esse erro. Tentei todas as soluções que encontrei no StackOverflow pela letra e ainda recebi este erro:Can't bind to 'routerlink' since it isn't a known native property

Esteja ciente de que o Visual Studio tem o hábito desagradável de formatação automática de texto quando você copia / cola código. Eu sempre recebi um pequeno ajuste instantâneo do VS13 (a caixa de camelo desaparece).

Este:

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

Torna-se:

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

É uma pequena diferença, mas o suficiente para acionar o erro. A parte mais feia é que essa pequena diferença ficava evitando a minha atenção toda vez que eu copiava e colava. Por mero acaso, vi essa pequena diferença e a resolvi.


4
Obrigado, você poderia ter mencionado a diferença entre "routerlink" e "routerLink". Angular 2 espera que "routerLink" esteja presente, mas encontre "routerlink"
Narendran Solai Sridharan

Obrigado, por algum motivo, algum tutorial usou o "roteador-link" com o traço no meio. Mas routerLink é a versão correta.
Windmaomao 16/08/19

O mesmo acontece com o webpack e o html-minifier, mas apenas na produção. adicione caseSensitive: true às opções do html-loader, consulte: github.com/SamanthaAdrichem/webpack-3.9.1-splitted-config-an‌ gular para uma configuração angular de trabalho 5 + webpack 3.9
Samantha Adrichem

12

Para> = V5

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

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

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

componente:

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

Para <V5

Também pode usar RouterLinkcomo um directivesie. directives: [RouterLink]. isso funcionou para mim

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},
])

Eu acho que isso não se aplica mais (Angular 5) etc.
Alexander Mills

10

Em geral, sempre que você recebe um erro como esse Can't bind to 'xxx' since it isn't a known native property, a causa mais provável é esquecer de especificar um componente ou uma diretiva (ou uma constante que contenha o componente ou a diretiva) na directivesmatriz de metadados. Esse é o caso aqui.

Como você não especificou RouterLinkou a constante ROUTER_DIRECTIVES- que contém o seguinte :

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

- na directivesmatriz, quando Angular analisa

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

não conhece a diretiva RouterLink (que usa o seletor de atributosrouterLink ). Como o Angular sabe qual é o aelemento, ele assume que [routerLink]="..."é uma ligação de propriedade para o aelemento. Mas, em seguida, descobre que routerLinknão é uma propriedade nativa dos aelementos, portanto, lança a exceção sobre a propriedade desconhecida.


Eu realmente nunca gostei da ambiguidade da sintaxe . Ou seja, considere

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

Apenas olhando para o HTML, não podemos dizer se whatIsThisé

  • uma propriedade nativa de something
  • o seletor de atributos de uma diretiva
  • uma propriedade de entrada de something

Precisamos saber quais directives: [...]são especificados nos metadados do componente / diretiva para interpretar mentalmente o HTML. E quando esquecemos de colocar algo na directivesmatriz, sinto que essa ambiguidade torna um pouco mais difícil a depuração.


7

Você tem no seu módulo

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

você tem que exportar o módulo RouteModule

exemplo:

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

para poder acessar as funcionalidades de todos os que importam este módulo.


5

Eu tentei todos os métodos mencionados acima. Mas nenhum método funciona para mim. Finalmente, eu tenho a solução para o problema acima e está funcionando para mim.

Eu tentei este método:

Em HTML:

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

No arquivo TS:

aboutPageLoad() {
    this.router.navigate(['/about']);
}

4

No meu caso, importei o RouterModule no módulo App, mas não o importei no meu módulo de recursos. Depois de importar o módulo roteador no meu EventModule, o erro desaparece.

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 {

 }

3

Se receber este erro durante o teste de unidade, escreva-o.

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

0

Eu realmente aprecio a resposta de @ raykrow quando alguém tem esse problema apenas em um arquivo de teste! Foi aí que eu o encontrei.

Como geralmente é útil ter outra maneira de fazer algo como backup, eu queria mencionar essa técnica que também funciona (em vez de importar RouterTestingModule):

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

(Normalmente, alguém usaria routerLinkem um <a>elemento, mas ajustaria o seletor de acordo com outros componentes.)

A segunda razão pela qual eu quis mencionar essa solução alternativa é que, embora ela tenha me servido bem em vários arquivos de especificação, tive um problema com ela em um caso:

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

Eu não conseguia entender como esse mock e meu ButtonComponentestavam usando o mesmo seletor; portanto, procurar uma abordagem alternativa me levou aqui à solução da @ raykrow.


0

Se você usa módulos compartilhados, basta adicionar RouterModule a um módulo em que seu componente é declarado e não se esqueça de adicionar <router-outlet></router-outlet>

Referenciado a partir daqui, o RouterLink não funciona


-4

Minha solução é simples. Estou usando [href] em vez de [routerLink]. Eu tentei todas as soluções para [routerLink]. Nenhum deles funciona no meu caso.

Aqui está a minha solução:

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

Em seguida, escreva a getPlanUrlfunção no arquivo TS.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.