javascript - Angular 4 Routing seltsames Verhalten: Kindmodul wird nicht gerendert, außer beim Seiten-Refresh
Ich habe nach einer Lösung für dieses seltsame Verhalten gesucht, jedoch ohne Erfolg.
Es gibt keine Fehler in der Angular 4 Konsole oder der JavaScript Konsole
- Verwendung von Angular CLI (Angular 4)
Ich bekomme extrem merkwürdiges Verhalten mit dem Angular-Router. Ich versuche, eine Kindroute zu laden, die ihr eigenes Modul hat, vom übergeordneten AppModule. Die Route befindet sich unter /products.
Im /products Modul (products.module.ts): Ich habe 3 Routen:
- /produkte/übersicht
- /produkte/intro [weitergeleitet von /produkte]
- /produkte/produkt/:product
Das Produktmodul soll seine eigene Navigationsleiste UNTER der globalen Navigationsleiste des AppModuls haben, die oberhalb des router-outlet im Template der Komponente products.component.html liegt.
Das Hauptproblem: Wenn ich die Seite lade (nicht über einen Angular routerLink) zu /products:
- beide Navigationsleisten sind sichtbar
- Die Seite, die GELADEN ist (z. B. /intro), hat die Navigationsleiste sichtbar, aber die untergeordnete Komponente (IntroComponent) ist NICHT sichtbar.
- JEDOCH, wenn ich zu einer anderen Unterroute innerhalb der /products Modulrouten navigiere (z. B. /overview oder /product/:product), wird sie einwandfrei angezeigt. Also ist die Route, die bei einem vollständigen Seiten-Refresh geladen wird, nicht sichtbar.
Der seltsamste Teil: Wenn ich die Seite lade (aktualisiere) auf einer Route, die nicht /products ist (z. B. /home), und dann die Hauptnavigationsleiste benutze, um zu /products zu navigieren:
- Die Navigationsleiste ist nicht sichtbar ?????
- Die Unterkomponente (z. B. /intro-Komponente) IST sichtbar
Das hat mir in den letzten Tagen eine Menge Hölle verursacht.
Jetzt etwas Code:
app.module.ts [Haupt-AppModul]
@NgModule({
declarations: [
AppComponent,
HomeComponent,
LoginComponent,
SignupComponent,
NotFoundComponent,
LogoutComponent,
ErrorComponent,
AboutComponent,
ApiComponent,
StatusComponent,
SupportComponent,
CustomersComponent,
JobsComponent,
TosComponent
],
imports: [
BrowserModule,
HttpModule,
FormsModule,
SharedModule,
//ProductsModule,
AppRoutingModule
],
providers: [
UserService,
AuthGuard,
ErrorService,
NavbarService,
MailerService,
IOService,
],
bootstrap: [AppComponent]
})
export class AppModule {
}
shared.module.ts -- Dies enthält meine ViewAppComponent (die nur ein Router-Outlet mit der globalen Navigationsleiste ist) und andere globale Komponenten (wie die Navigationsleiste und den Footer, die auf allen Routen angezeigt werden sollen)
@NgModule({
imports: [
CommonModule,
RouterModule
],
declarations: [ViewAppComponent, FooterComponent, NavbarComponent],
exports: [CommonModule, ViewAppComponent, FooterComponent, NavbarComponent]
})
export class SharedModule { }
app-routing.module.ts
const routes: Routes = [
{
path: '',
component: ViewAppComponent,
children: [
{path: 'products', loadChildren: () => ProductsModule}, // where im trying to load my products module from the main module
{path: 'home', component: HomeComponent},
{path: 'about', component: AboutComponent},
{path: 'api', component: ApiComponent},
{path: 'status', component: StatusComponent},
{path: 'support', component: SupportComponent},
{path: 'customers', component: CustomersComponent},
{path: 'jobs', component: JobsComponent},
{path: 'tos', component: TosComponent},
{path: 'signup', component: SignupComponent, canActivate: [AuthGuard]},
{path: 'logout', component: LogoutComponent, canActivate: [AuthGuard]},
{path: 'login', component: LoginComponent},
{path: 'error', component: ErrorComponent, canActivate: [ErrorService]},
{path: "404", component: NotFoundComponent},
{path: '', redirectTo: '/home', pathMatch: 'full'},
]
},
{path: "admin", loadChildren: "./admin/admin.module#AdminModule"},
{path: '**', redirectTo: '/404'}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
products.module.ts [Haupt-Produktmodul, in dem ich versuche, Unterrouten zu laden]
@NgModule({
imports: [
CommonModule,
FormsModule,
SharedModule,
RouterModule,
ProductsRoutingModule
],
declarations: [ProductsComponent, OverviewComponent, IntroComponent, NavigationComponent, ProductComponent],
exports: [
ProductsComponent, OverviewComponent, IntroComponent, NavigationComponent, ProductComponent, RouterModule, ProductsRoutingModule
]
})
export class ProductsModule {
}
products-routing.module.ts [Router für das Produkt-Submodul]
export const productRoutes: Routes = [
{
path: '',
component: ProductsComponent,
children: [
{
path: 'overview',
component: OverviewComponent,
},
{
path: 'intro',
component: IntroComponent
},
{
path: 'product/:product',
component: ProductComponent
},
{
path: '',
redirectTo: '/products/intro',
pathMatch: 'full'
},
{
path: '**',
redirectTo: '/404',
pathMatch: 'full'
}
]
}
];
@NgModule({
imports: [RouterModule.forChild(productRoutes)],
exports: [RouterModule]
})
export class ProductsRoutingModule {}
products.component.html [Vorlage für Produkte mit Platzhalter für Unterkomponenten in Produkten]
<h1>Products</h1>
<br/>
<app-product-navigation></app-product-navigation>
<br/>
<router-outlet></router-outlet>
navigation.component.html [app-product-navigation Komponentenvorlage]
<nav class="navbar navbar-info" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#products-navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse" id="products-navbar-collapse">
<ul class="nav navbar-nav">
<li routerLinkActive="active"><a routerLink="/products/intro">Intro</a></li>
<li routerLinkActive="active"><a routerLink="/products/overview">Overview</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Products <b class="caret"></b></a>
<ul class="dropdown-menu">
<li routerLinkActive="active"><a routerLink="/products/product/reflex">Reflex</a></li>
<li routerLinkActive="active"><a routerLink="/products/product/override">Project Override</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<br/>
Ich werde auch meine package.json-Abhängigkeiten für die Versionen bereitstellen, ich benutze ng serve zum Testen.
"dependencies": {
"@agm/core": "1.0.0-beta.0",
"@angular/animations": "4.3.1",
"@angular/cdk": "2.0.0-beta.10",
"@angular/common": "4.3.1",
"@angular/compiler": "4.3.1",
"@angular/core": "4.3.1",
"@angular/forms": "4.3.1",
"@angular/http": "4.3.1",
"@angular/material": "2.0.0-beta.10",
"@angular/platform-browser": "4.3.1",
"@angular/platform-browser-dynamic": "4.3.1",
"@angular/platform-server": "4.3.1",
"@angular/router": "4.3.1",
"angular2-material-datepicker": "0.5.0",
"animate.css": "3.5.2",
"arrive": "2.3.1",
"bootstrap": "3.3.5",
"bootstrap-material-design": "0.5.10",
"bootstrap-notify": "3.1.3",
"bootstrap-select": "1.12.2",
"bootstrap-tagsinput": "0.7.1",
"chartist": "0.9.4",
"chartist-plugin-zoom": "0.4.0",
"core-js": "2.4.1",
"datatables": "1.10.12",
"datatables.net-bs": "1.10.12",
"datatables.net-responsive": "2.1.1",
"eonasdan-bootstrap-datetimepicker": "4.17.47",
"fullcalendar": "3.4.0",
"googleapis": "19.0.0",
"jasny-bootstrap": "3.1.3",
"jquery": "1.12.4",
"moment": "2.18.1",
"moment-timezone": "0.4.0",
"ng2-nouislider": "1.6.1",
"ng2-select": "1.2.0",
"ngx-chips": "1.4.6",
"nouislider": "9.2.0",
"rxjs": "^5.4.2",
"twitter-bootstrap-wizard": "1.2.0",
"typescript": "2.3.4",
"validate": "3.0.1",
"web-animations-js": "2.2.2",
"zone.js": "0.8.4"
},
"devDependencies": {
"@angular/cli": "1.4.2",
"@angular/compiler-cli": "4.3.1",
"@types/bootstrap": "3.3.32",
"@types/chartist": "0.9.34",
"@types/jasmine": "2.5.38",
"@types/jquery": "1.10.31",
"@types/node": "6.0.73",
"codelyzer": "2.0.0",
"jasmine-core": "2.5.2",
"jasmine-spec-reporter": "3.2.0",
"karma": "1.4.1",
"karma-chrome-launcher": "2.0.0",
"karma-cli": "1.0.1",
"karma-coverage-istanbul-reporter": "0.2.0",
"karma-jasmine": "1.1.0",
"karma-jasmine-html-reporter": "0.2.2",
"node-sass": "^4.5.3",
"protractor": "5.1.0",
"ts-node": "2.0.0",
"tslint": "4.5.0",
"typescript": "2.3.4"
}
}
Dies ist mein erster 'suche nach Hilfe'-Beitrag auf Stackoverflow, also lasst mich wissen, ob es etwas gibt, das ich verbessern kann.
Ich habe versucht, verschiedene Formen und Tutorials zu recherchieren und habe die Angular-Dokumentation für Routing verwendet.
Bearbeiten: Einige Bilder hinzufügen, um die Situation besser zu verdeutlichen
Startseite: http://prntscr.com/gskex5
Produkte [/products/intro] (über routerLink navigiert): http://prntscr.com/gskf2h (die Produkte-Navbar fehlt) Beim Aktualisieren wird die Navbar sichtbar, aber die Intro-Komponente ist verschwunden: http://prntscr.com/gskfaq
Wenn ich jedoch auf eine andere Komponente in der Produktnavigation klicke, funktioniert es richtig: http://prntscr.com/gskfhf
Wenn ich aktualisiere, verschwindet die Komponente, und die Navigation bleibt: http://prntscr.com/gskfna und jetzt, aus welchem Grund auch immer, funktioniert es, wenn ich zurück zum Intro gehe, richtig: http://prntscr.com/gskfra
Also im Grunde genommen, egal welche Route beim erstmaligen Laden der Seite geladen wird, sie hat ein Problem [Komponente ist nicht sichtbar]. Wenn die ursprünglich geladene Route nicht /products ist, ist die Produkt-Navigationsleiste nicht sichtbar.
Antwort #1
Für diese eher seltsame Situation konnte ich dieses seltsame Verhalten beheben, indem ich eine neue Angular 4 App mit dem angular-cli erstellt habe: ng new
Ich vermute, es hatte etwas mit der Version von Angular zu tun, die ich verwendete.
Für mein neues Projekt sind die @angular-Versionen auf **^4.0.0** festgelegt.
Im alten Projekt wurden die Versionen auf 4.3.1 gesetzt
Ich würde vermuten, dass es etwas mit einer der Änderungen in den Fehlerbehebungen für v4.3.1 zu tun hat:
- Router: canDeactivate-Guards sollten von unten nach oben ausgeführt werden (1ac78bf), schließt #15657
- Router: sollte zur gleichen URL navigieren, wenn sich die Konfiguration ändert (4340bea), schließt #15535
- Router: sollte Resolver für dieselbe Route gleichzeitig ausführen (ec89f37), schließt #14279
- Router: Terminal Route im benutzerdefinierten Matcher (5d275e9)
Zusammenfassung
verwenden Sie die neueste stabile Version von ng4