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!


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.


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/


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ą.


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

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.


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ł.


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']);
}

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 {

 }

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

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.



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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.