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!

Lester Burnham
fonte
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.

Günter Zöchbauer
fonte
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/

rayepps
fonte
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.

Adrian Moisa
fonte
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},
])
Shaishab Roy
fonte
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.

Mark Rajcok
fonte
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.

alehn96
fonte
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']);
}
Sunil Kumar KK
fonte
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 {

 }
Code-EZ
fonte
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],
 });
}));
Deeksha Bilochi
fonte
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.

Michael Sorens
fonte
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

Yevheniy Potupa
fonte
-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.

G Chen
fonte