Wyjątek Angular2: Nie można powiązać z „routLink”, ponieważ nie jest to znana właściwość natywna

277

Oczywiście beta dla Angular2 jest nowszy niż nowy, więc nie ma tam wielu informacji, ale staram się robić to, co uważam za dość podstawowy routing.

Włamywanie się za pomocą kodu szybkiego startu i innych fragmentów ze strony https://angular.io spowodowało następującą strukturę plików:

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

Pliki są wypełniane w następujący sposób:

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

Próba uruchomienia tego kodu powoduje błąd:

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

Znalazłem tutaj niejasno powiązany problem; po aktualizacji do angular2.0.0-beta.0 zepsute dyrektywy router-link . Jednak „działający przykład” w jednej z odpowiedzi opiera się na kodzie wcześniejszym niż beta - co może nadal działać, ale chciałbym wiedzieć, dlaczego utworzony przeze mnie kod nie działa.

Wszelkie wskazówki zostaną z wdzięcznością przyjęte!

Lester Burnham
źródło
4
Druga kwestia ma coś innego: directives: [ROUTER_DIRECTIVES].
Eric Martinez,
1
Ten sam błąd pojawia się nawet w przypadku ROUTER_DIRECTIVES. @Component({selector: "app"}) @View({templateUrl: "app.html", directives: [ROUTER_DIRECTIVES, RouterLink]})
phil
8
Po dodaniu directives: [ROUTER_DIRECTIVES]i zmianie z [router-link] na [routerLink] nie pojawia się już błąd.
phil

Odpowiedzi:

392

> = RC.5

zaimportuj RouterModule Zobacz także 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

Brakuje twojego kodu

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

Nie można używać dyrektyw takich jak routerLinklub router-outletbez podawania ich do wiadomości komponentowi.

Podczas gdy w nazwach dyrektyw zmieniono rozróżnianie wielkości liter w Angular2, elementy nadal używają -nazwy, <router-outlet>aby być zgodnym ze specyfikacją składników WWW, która wymaga -w nazwie elementów niestandardowych.

zarejestruj się globalnie

Aby udostępnić ROUTER_DIRECTIVESglobalnie, dodaj tego dostawcę do bootstrap(...):

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

to nie jest już konieczne dodawanie ROUTER_DIRECTIVESdo każdego komponentu.

Günter Zöchbauer
źródło
1
tak, możesz przypisać wiele dyrektyw podczas ładowania aplikacji w następujący sposób: -provide(PLATFORM_DIRECTIVES, {useValue: [ROUTER_DIRECTIVES, FORM_DIRECTIVES, ETC...], multi: true})
Pardeep Jain
1
Zgadza się, ale FORM_DIRECTIVESPLATFORM_DIRECTIVESjuż domyślnie uwzględnione.
Günter Zöchbauer
2
To było świetne, dzięki. Przydało mi się to również, gdy próbowałem złożyć wszystko w całość: stackoverflow.com/questions/34391790/...
Jeff
Może głupie pytanie tutaj, ale co to jest RC.1, RC.2 tutaj? Używam kątowego 2.1.2, który to RC?
Jian Chen
1
@AlexanderMills, dlaczego przestraszy Cię stary andwers? Stare odpowiedzi są testowane w walce i dlatego są bardzo godne zaufania; p
Günter Zöchbauer
116

Dla ludzi, którzy znaleźli to przy próbie testy zakończą ponieważ poprzez npm testlub ng testza pomocą Karma czy cokolwiek innego. Twój moduł .spec wymaga specjalnego importu testującego router, aby móc budować.

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

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

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

rayepps
źródło
2
To świetny haczyk! Mój projekt nie miał problemu z normalnym działaniem, specmusiałem to dodać w pliku. Dzięki @raykrow!
kbpontius
1
Potwierdzony do pracy również w kanciastym 4. Dzięki za to!
JCisar
To musi być zaakceptowana odpowiedź, zaakceptowana odpowiedź jest zła, ponieważ podczas importowania RouterModulemusisz zadzwonić, forRootaby zaspokoić moduł, a następnie powinieneś dostarczyć BASE_HREF...
Milad
1
Czy masz pojęcie, czy jest inaczej w Angular 5+? Otrzymuję podobny błąd Can't bind to 'active' since it isn't a known property of 'a'.w kilku moich testach jednostkowych i zaimportowałem RouterTestingModule.
Stuart Updegrave,
25

Uwaga przy programowaniu w Visual Studio (2013)

Zmarnowałem 4 do 5 godzin, próbując debugować ten błąd. Wypróbowałem wszystkie rozwiązania, które znalazłem na StackOverflow, i nadal otrzymuję ten błąd:Can't bind to 'routerlink' since it isn't a known native property

Pamiętaj, że Visual Studio ma nieprzyjemny zwyczaj automatycznego formatowania tekstu podczas kopiowania / wklejania kodu. Zawsze otrzymywałem niewielką natychmiastową regulację z VS13 (obudowa wielbłąda znika).

To:

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

Staje się:

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

To niewielka różnica, ale wystarczająca do wyzwolenia błędu. Najbrzydsze jest to, że ta niewielka różnica po prostu unikała mojej uwagi za każdym razem, gdy kopiowałem i wklejałem. Przez przypadek zobaczyłem tę małą różnicę i rozwiązałem ją.

Adrian Moisa
źródło
4
Dziękujemy, mogłeś wspomnieć o różnicy w przypadku między „routlink” a „routerLink”. Angular 2 oczekuje, że „routerLink” będzie obecny, ale znajdzie „routerlink”
Narendran Solai Sridharan
Dziękuję z jakiegoś powodu w tutorialu wykorzystano „router-link” z myślnikiem pomiędzy nimi. Ale routerLink jest poprawną wersją.
windmaomao
To samo dzieje się z webpack i html-minifier, ale tylko w produkcji. dodaj caseSensitive: true do opcji modułu ładującego HTML patrz: github.com/SamanthaAdrichem/webpack-3.9.1-splitted-config-an‌ gular dla działającego konfiguratora
webpack
12

Dla> = V5

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

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

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

składnik:

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

Dla <V5

Można również użyć RouterLinkjako directivestj. directives: [RouterLink]. to działało dla mnie

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
źródło
Nie sądzę, żeby miało to już zastosowanie (Angular 5) itd.
Alexander Mills
10

Zasadniczo, gdy pojawi się taki błąd Can't bind to 'xxx' since it isn't a known native property, najbardziej prawdopodobną przyczyną jest zapomnienie podania komponentu lub dyrektywy (lub stałej zawierającej komponent lub dyrektywę) w directivestablicy metadanych. Tak jest w tym przypadku.

Ponieważ nie określono RouterLinkani stałej ROUTER_DIRECTIVES- która zawiera następujące elementy :

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

- w directivestablicy, a następnie podczas analizy kątowej

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

nie wie o dyrektywie RouterLink (która korzysta z selektora atrybutówrouterLink ). Ponieważ Angular nie wie, co to ajest element, zakłada, że [routerLink]="..."jest to wiązanie właściwościa elementu. Ale potem odkrywa, że routerLinknie jest natywną własnością aelementów, dlatego zgłasza wyjątek dotyczący nieznanej właściwości.


Nigdy tak naprawdę nie lubiłem dwuznaczności składni . To znaczy, zastanów się

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

Po prostu patrząc na HTML nie możemy stwierdzić, czy tak whatIsThisjest

  • własność natywna something
  • selektor atrybutów dyrektywy
  • właściwość wejściowa something

Musimy wiedzieć, które directives: [...]są określone w metadanych komponentu / dyrektywy, aby mentalnie interpretować HTML. A kiedy zapomnimy umieścić coś w directivestablicy, czuję, że ta dwuznaczność utrudnia debugowanie.

Mark Rajcok
źródło
7

Masz w swoim module

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

musisz wyeksportować moduł RouteModule

przykład:

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

aby mieć dostęp do funkcji dla wszystkich, którzy importują ten moduł.

alehn96
źródło
5

Wypróbowałem wszystkie metody, które są wymienione powyżej, ale żadna metoda nie działa dla mnie. W końcu mam rozwiązanie dla powyższego problemu i działa dla mnie.

Próbowałem tej metody:

W HTML:

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

W pliku TS:

aboutPageLoad() {
    this.router.navigate(['/about']);
}
Sunil Kumar KK
źródło
4

W moim przypadku zaimportowałem RouterModule do modułu aplikacji, ale nie zaimportowałem go do mojego modułu funkcji. Po zaimportowaniu modułu routera do modułu EventModule błąd znika.

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
źródło
3

Jeśli otrzymujesz ten błąd podczas testowania jednostki, napisz to.

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

Naprawdę doceniam odpowiedź @ raykrow, gdy ten problem występuje tylko w pliku testowym! Właśnie tam go spotkałem.

Ponieważ często pomocne jest posiadanie innego sposobu wykonania kopii zapasowej, chciałem wspomnieć o tej technice, która również działa (zamiast importowania RouterTestingModule):

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

(Zazwyczaj używa się go routerLinkna <a>elemencie, ale odpowiednio dostosowuje selektor dla innych komponentów.)

Drugim powodem, dla którego chciałem wspomnieć o tym alternatywnym rozwiązaniu, jest to, że chociaż dobrze mi to służyło w wielu plikach specyfikacji, w jednym przypadku napotkałem problem:

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

Nie mogłem do końca zrozumieć, w jaki sposób ten kpina i ja ButtonComponentużywaliśmy tego samego selektora, więc poszukiwanie alternatywnego podejścia doprowadziło mnie tutaj do rozwiązania @ raykrow.

Michael Sorens
źródło
0

Jeśli korzystasz z modułów współdzielonych, po prostu dodaj RouterModule do modułu, w którym deklarowany jest twój komponent i nie zapomnij go dodać <router-outlet></router-outlet>

Odwołany tutaj RouterLink nie działa

Jewhenij Potupa
źródło
-4

Moje rozwiązanie jest proste. Używam [href] zamiast [routerLink]. Wypróbowałem wszystkie rozwiązania dla [routerLink]. Żadne z nich nie działa w moim przypadku.

Oto moje rozwiązanie:

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

Następnie zapisz getPlanUrlfunkcję w pliku TS.

G Chen
źródło