Excepción Angular2: no se puede vincular a 'routerLink' ya que no es una propiedad nativa conocida

277

Obviamente, la versión beta de Angular2 es más nueva que nueva, por lo que no hay mucha información disponible, pero estoy tratando de hacer lo que creo que es una ruta bastante básica.

Hackear con el código de inicio rápido y otros fragmentos del sitio web https://angular.io ha dado como resultado la siguiente estructura de archivos:

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

Con los archivos que se rellenan de la siguiente manera:

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

Intentar ejecutar este código produce el error:

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

Encontré un problema vagamente relacionado aquí; directivas de enlace de enrutador rotas después de actualizar a angular2.0.0-beta.0 . Sin embargo, el "ejemplo de trabajo" en una de las respuestas se basa en el código pre-beta, que bien podría funcionar, pero me gustaría saber por qué el código que he creado no funciona.

Cualquier sugerencia sería recibida con gratitud!

Lester Burnham
fuente
44
La otra pregunta tiene algo diferente: directives: [ROUTER_DIRECTIVES].
Eric Martinez
1
Recibo el mismo error incluso con ROUTER_DIRECTIVES. @Component({selector: "app"}) @View({templateUrl: "app.html", directives: [ROUTER_DIRECTIVES, RouterLink]})
Phil
8
Con la adición directives: [ROUTER_DIRECTIVES]y el cambio de [router-link] a [routerLink] ya no obtengo el error.
phil

Respuestas:

392

> = RC.5

importar el RouterModule Ver también 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

Falta tu código

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

No puede usar directivas como routerLinko router-outletsin darlas a conocer a su componente.

Si bien los nombres de las directivas se cambiaron para distinguir entre mayúsculas y minúsculas en Angular2, los elementos aún se usan -en el nombre <router-outlet>para ser compatibles con las especificaciones de componentes web que requieren un -nombre en el nombre de los elementos personalizados.

registrarse a nivel mundial

Para que esté ROUTER_DIRECTIVESdisponible globalmente, agregue este proveedor a bootstrap(...):

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

entonces ya no es necesario agregar ROUTER_DIRECTIVESa cada componente.

Günter Zöchbauer
fuente
1
sí, también puede asignar varias directivas al momento de iniciar su aplicación de esta manera: -provide(PLATFORM_DIRECTIVES, {useValue: [ROUTER_DIRECTIVES, FORM_DIRECTIVES, ETC...], multi: true})
Pardeep Jain
1
Así es, pero ya FORM_DIRECTIVESestán incluidos PLATFORM_DIRECTIVESpor defecto.
Günter Zöchbauer
2
Esto fue genial, gracias. También encontré esto útil cuando intenté ponerlo todo junto: stackoverflow.com/questions/34391790/…
Jeff
Tal vez una pregunta estúpida aquí, pero ¿qué es RC.1, RC.2 aquí? Estoy usando angular 2.1.2, ¿qué RC es?
Jian Chen el
1
@AlexanderMills ¿por qué te asustan las viejas torres? Las respuestas anteriores se prueban en la batalla y, por lo tanto, son muy confiables; p
Günter Zöchbauer
116

Para las personas que encuentran esto cuando intentan ejecutar pruebas porque a través npm testo ng testutilizando Karma o cualquier otra cosa. Su módulo .spec necesita una importación de prueba de enrutador especial 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
fuente
2
Esta es una gran captura! Mi proyecto no tenía ningún problema con el funcionamiento normal, fue en el specarchivo que tuve que agregar esto. Gracias @raykrow!
kbpontius
1
Confirmado para trabajar en angular 4 también. ¡Gracias por esto!
JCisar
Esta debe ser la respuesta aceptada, la respuesta aceptada es incorrecta, porque al importar RouterModule, debe llamar forRootpara satisfacer el módulo y luego debe proporcionar el BASE_HREFy ...
Milad
1
¿Tienes alguna idea de si esto es diferente para Angular 5+? Recibo un error similar Can't bind to 'active' since it isn't a known property of 'a'.en varias de las pruebas de mi unidad y he importado RouterTestingModule.
Stuart Updegrave
25

Palabra de precaución al codificar con Visual Studio (2013)

He perdido 4 a 5 horas tratando de depurar este error. Probé todas las soluciones que encontré en StackOverflow por carta y todavía recibí este error:Can't bind to 'routerlink' since it isn't a known native property

Tenga en cuenta que Visual Studio tiene el desagradable hábito de autoformatar texto cuando copia / pega código. Siempre obtuve un pequeño ajuste instantáneo de VS13 (el caso del camello desaparece).

Esta:

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

Se convierte en:

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

Es una pequeña diferencia, pero suficiente para provocar el error. La parte más fea es que esta pequeña diferencia seguía evitando mi atención cada vez que copiaba y pegaba. Por pura casualidad, vi esta pequeña diferencia y la resolví.

Adrian Moisa
fuente
44
Gracias, podría haber mencionado la diferencia en el caso entre "routerlink" vs "routerLink". Angular 2 espera que "routerLink" esté presente pero encuentra "routerlink"
Narendran Solai Sridharan
Gracias, por alguna razón, algún tutorial usó "router-link" con un guión en el medio. Pero routerLink es la versión correcta.
windmaomao
Lo mismo sucede con webpack y html-minifier, pero solo en producción. add caseSensitive: fiel a las opciones de html-loader, consulte: github.com/SamanthaAdrichem/webpack-3.9.1-splitted-config-an‌ gular para una configuración angular 5 + webpack 3.9 en funcionamiento
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

También se puede usar RouterLinkcomo un directivesie. directives: [RouterLink]. eso funcionó para mí

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
fuente
No creo que esto se aplique más (Angular 5) etc.
Alexander Mills
10

En general, cada vez que Can't bind to 'xxx' since it isn't a known native propertyaparece un error , la causa más probable es olvidarse de especificar un componente o una directiva (o una constante que contenga el componente o la directiva) en la directivesmatriz de metadatos. Tal es el caso aquí.

Como no especificó RouterLinko la constante ROUTER_DIRECTIVES, que contiene lo siguiente :

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

- en la directivesmatriz, entonces cuando Angular analiza

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

no conoce la directiva RouterLink (que usa el selector de atributosrouterLink ). Dado que Angular sabe qué es el aelemento, se supone que [routerLink]="..."es un enlace de propiedad para el aelemento. Pero luego descubre que routerLinkno es una propiedad nativa de los aelementos, por lo tanto, arroja la excepción sobre la propiedad desconocida.


Nunca me ha gustado realmente la ambigüedad de la sintaxis . Es decir, considera

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

Simplemente mirando el HTML no podemos decir si whatIsThises

  • una propiedad nativa de something
  • selector de atributos de una directiva
  • una propiedad de entrada de something

Tenemos que saber cuáles directives: [...]se especifican en los metadatos del componente / directiva para interpretar mentalmente el HTML. Y cuando olvidamos poner algo en la directivesmatriz, creo que esta ambigüedad hace que sea un poco más difícil de depurar.

Mark Rajcok
fuente
7

Tienes en tu modulo

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

tienes que exportar el módulo RouteModule

ejemplo:

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

para poder acceder a las funcionalidades para todos los que importan este módulo.

alehn96
fuente
5

He probado todos los métodos, que se mencionan anteriormente. Pero ningún método funciona para mí. Finalmente obtuve una solución para el problema anterior y está funcionando para mí.

Probé este método:

En HTML:

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

En el archivo TS:

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

En mi caso, importé el RouterModule en el módulo de la aplicación pero no importé en mi módulo de funciones. Después de importar el módulo de enrutador en mi EventModule, el error 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
fuente
3

Si obtiene este error durante la prueba de la unidad, escriba esto.

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

¡Realmente aprecio la respuesta de @ raykrow cuando uno tiene este problema solo en un archivo de prueba! Ahí es donde lo encontré.

Como a menudo es útil tener otra forma de hacer algo como respaldo, quería mencionar esta técnica que también funciona (en lugar de importar RouterTestingModule):

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

(Normalmente, se usaría routerLinken un <a>elemento pero se ajustaría el selector en consecuencia para otros componentes).

La segunda razón por la que quería mencionar esta solución alternativa es que, aunque me sirvió bien en varios archivos de especificaciones, me encontré con un problema en un 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

No pude entender cómo este simulacro y mi ButtonComponentestaban usando el mismo selector, por lo que la búsqueda de un enfoque alternativo me llevó aquí a la solución de @ raykrow.

Michael Sorens
fuente
0

Si usa módulos compartidos, simplemente agregue RouterModule a un Módulo donde se declare su componente y no olvide agregar <router-outlet></router-outlet>

Referenciado desde aquí RouterLink no funciona

Yevheniy Potupa
fuente
-4

Mi solución es simple. Estoy usando [href] en lugar de [routerLink]. He probado todas las soluciones para [routerLink]. Ninguno de ellos funciona en mi caso.

Aquí está mi solución:

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

Luego escriba la getPlanUrlfunción en el archivo TS.

G Chen
fuente