And*_*ose 13 routing ngoninit angular
我有一个非常奇怪的问题,Angular 2路由到我ngOnInit
在路由到的组件中的两次被调用,并且浏览器中的路由被重置为原始路由.
我有一个NotificationListComponent
和NotificationEditComponent
一个MaintenanceModule
.
在我的根目录中AppModule
,我设置了RouterModule
将任何未映射的路由重定向到/maintenance/list
.
app.module.ts:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpModule,
RouterModule.forRoot([
{path: "", redirectTo: "maintenance/list", pathMatch: "full"},
{path: "**", redirectTo: "maintenance/list", pathMatch: "full"}
], {useHash: true}),
CoreModule.forRoot({notificationUrl: "http://localhost:8080/notification-service/notifications"}),
MaintenanceModule
],
providers: [NotificationService],
bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)
而且我/maintenance/list
在我的路线中定义了MaintenanceModule
指向我NotificationListComponent
的/maintenance/edit/:id
路线,以及指向我的路线NotificationEditComponent
.
maintenance.module.ts:
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{path: "maintenance/list", component: NotificationListComponent, pathMatch: 'full'},
{path: "maintenance/edit/:id", component: NotificationEditComponent, pathMatch: 'full'}
]),
FormsModule
],
declarations: [
NotificationListComponent,
NotificationEditComponent
]
})
export class MaintenanceModule {}
Run Code Online (Sandbox Code Playgroud)
当我的应用程序加载时,它正确地遵循/maintenance/list
路由,我可以在列表中看到我的所有通知.对于列表中的每个通知,都有一个编辑图标,其click
事件绑定到edit(id: number)
我的方法中NotificationListComponent
notification-list.component.ts:
@Component({
templateUrl: 'notification-list.component.html'
})
export class NotificationListComponent implements OnInit {
notifications: Notification[];
errorMessage: string;
constructor(private _notificationService: NotificationService,
private _router: Router) {}
ngOnInit(): void {
this._notificationService.getNotifications()
.subscribe(
notifications => this.notifications = notifications,
error => this.errorMessage = <any>error);
}
clearError(): void {
this.errorMessage = null;
}
}
Run Code Online (Sandbox Code Playgroud)
notification-list.component.html:
<div class="row">
<h1>Notification Maintenance</h1>
<div *ngIf="errorMessage" class="alert-box alert">
<span>{{errorMessage}}</span>
<a class="right" (click)="clearError()">×</a>
</div>
<p-dataTable [value]="notifications" [sortField]="'code'" [responsive]="true" [sortOrder]="1" [rows]="10" [paginator]="true" [rowsPerPageOptions]="[10,50,100]">
<p-header>Available Notifications</p-header>
<p-column [field]="'code'" [header]="'Code'" [sortable]="true" [style]="{'width':'10%'}"></p-column>
<p-column [field]="'name'" [header]="'Name'" [sortable]="true" [style]="{'width':'40%'}"></p-column>
<p-column [field]="'roles'" [header]="'Roles'" [style]="{'width':'40%'}"></p-column>
<p-column [field]="'notificationId'" [header]="'Edit'" [style]="{'width':'10%'}">
<template let-row="rowData" pTemplate="body">
<a [routerLink]="'/maintenance/edit/' + row['notificationId']"><span class="fa fa-pencil fa-2x"></span></a>
</template>
</p-column>
</p-dataTable>
</div>
Run Code Online (Sandbox Code Playgroud)
如您所见,该edit(id: number)
方法应导航到/maintenance/edit/:id
路线.当我单击图标导航到该路线时,浏览器会在地址栏中闪烁正确的路线(例如localhost:4200/#/maintenance/edit/2
),但地址栏中的路线会立即变回localhost:4200/#/maintenance/list
.即使路由返回到/maintenance/list
地址栏中,我NotificationEditComponent
仍然可以在实际应用程序中看到.但是,我可以看到该ngOnInit
方法在我的调用中被调用了两次NotificationEditComponent
,因为它id
被记录到控制台两次,如果我在ngOnInit
函数中放置一个断点,它会两次触发该断点.
notification-edit.component.ts:
@Component({
templateUrl: "notification-edit.component.html"
})
export class NotificationEditComponent implements OnInit{
notification: Notification;
errorMessage: string;
constructor(private _notificationService: NotificationService,
private _route: ActivatedRoute,
private _router: Router) {
}
ngOnInit(): void {
let id = +this._route.snapshot.params['id'];
console.log(id);
this._notificationService.getNotification(id)
.subscribe(
notification => this.notification = notification,
error => this.errorMessage = <any>error
);
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎也导致了其他问题,因为当尝试将input
值绑定到我NotificationEditComponent
使用的值时,例如[(ngModel)]="notification.notificationId"
,该值未显示在屏幕上,即使我可以看到Augury chrome扩展,以及记录对象到控制台,该值填充在组件中.
notification-edit.component.html:
<div class="row">
<h1>Notification Maintenance</h1>
<div *ngIf="errorMessage" class="alert-box alert">
<span>{{errorMessage}}</span>
<a class="right" (click)="clearError()">×</a>
</div>
<p-fieldset [legend]="'Edit Notification'">
<label for="notificationId">ID:
<input id="notificationId" type="number" disabled [(ngModel)]="notification.notificationId"/>
</label>
</p-fieldset>
</div>
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么会发生这种情况?
我删除了对它的调用NotificationService
,并用一些模拟数据替换它们,然后路由开始工作了!但是一旦我添加了对我的服务的调用,我就会遇到上面描述的相同问题.我甚至删除了CoreModule
,只是直接将服务添加到我的MaintenanceModule
,并且每当我使用实际服务而不仅仅是模拟数据时仍然会遇到相同的问题.
notification.service.ts:
@Injectable()
export class NotificationService {
private _notificationUrl : string = environment.servicePath;
constructor(private _http: Http) {
}
getNotifications(): Observable<Notification[]> {
return this._http.get(this._notificationUrl)
.map((response: Response) => <Notification[]>response.json())
.catch(this.handleGetError);
}
getNotification(id: number): Observable<Notification> {
return this._http.get(this._notificationUrl + "/" + id)
.map((response: Response) => <Notification>response.json())
.catch(this.handleGetError);
}
postNotification(notification: Notification): Observable<number> {
let id = notification.notificationId;
let requestUrl = this._notificationUrl + (id ? "/" + id : "");
return this._http.post(requestUrl, notification)
.map((response: Response) => <number>response.json())
.catch(this.handlePostError);
}
private handleGetError(error: Response) {
console.error(error);
return Observable.throw('Error retrieving existing notification(s)!');
}
private handlePostError(error: Response) {
console.error(error);
return Observable.throw('Error while attempting to save notification!');
}
}
Run Code Online (Sandbox Code Playgroud)
服务似乎运行正常 - 我可以看到端点成功返回数据,当我NotificationEditComponent
用Augury chrome扩展查看我的数据时,我可以看到数据看起来正确.但是数据不会显示在模板中,/maintenance/list
即使/maintenance/edit/:id
仍显示路径模板,URL中的路径也会返回.
正如@ user3249448所建议的那样,我将以下内容添加到我AppComponent
的调试中:
constructor(private _router: Router) {
this._router.events.pairwise().subscribe((event) => {
console.log(event);
});
}
Run Code Online (Sandbox Code Playgroud)
这是当我点击其中一个"编辑"链接时的输出:
从@ user3249448获得调试帮助后,终于能够解决问题了.
事实证明我得到了这个NavigationError
,即使没有错误记录到控制台:
这是完整的堆栈跟踪:
TypeError: Cannot read property 'notificationId' of undefined
at CompiledTemplate.proxyViewClass.View_NotificationEditComponent0.detectChangesInternal (/MaintenanceModule/NotificationEditComponent/component.ngfactory.js:487:49)
at CompiledTemplate.proxyViewClass.AppView.detectChanges (http://localhost:4200/vendor.bundle.js:80125:14)
at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (http://localhost:4200/vendor.bundle.js:80320:44)
at CompiledTemplate.proxyViewClass.AppView.internalDetectChanges (http://localhost:4200/vendor.bundle.js:80110:18)
at CompiledTemplate.proxyViewClass.View_NotificationEditComponent_Host0.detectChangesInternal (/MaintenanceModule/NotificationEditComponent/host.ngfactory.js:29:19)
at CompiledTemplate.proxyViewClass.AppView.detectChanges (http://localhost:4200/vendor.bundle.js:80125:14)
at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (http://localhost:4200/vendor.bundle.js:80320:44)
at ViewRef_.detectChanges (http://localhost:4200/vendor.bundle.js:60319:20)
at RouterOutlet.activate (http://localhost:4200/vendor.bundle.js:65886:42)
at ActivateRoutes.placeComponentIntoOutlet (http://localhost:4200/vendor.bundle.js:24246:16)
at ActivateRoutes.activateRoutes (http://localhost:4200/vendor.bundle.js:24213:26)
at http://localhost:4200/vendor.bundle.js:24149:58
at Array.forEach (native)
at ActivateRoutes.activateChildRoutes (http://localhost:4200/vendor.bundle.js:24149:29)
at ActivateRoutes.activate (http://localhost:4200/vendor.bundle.js:24123:14)
Run Code Online (Sandbox Code Playgroud)
基本上,我的模板在返回对我的Web服务的调用之前被呈现,并且我的模板无法正确呈现,因为notification
是undefined
,所以我得到了这个NavigationError
,这导致了所描述的行为(似乎不应该是这个错误应该是登录到控制台而无需在您的AppComponent
?)中添加额外的调试代码.
为了解决这个问题,我不得不做的是一个添加*ngIf
到我的fieldset
包含所有有关的信息notification
.
<p-fieldset [legend]="'Edit Notification'" *ngIf="notification">
Run Code Online (Sandbox Code Playgroud)
现在,一旦从Web服务返回数据,我的模板就会正确加载.
归档时间: |
|
查看次数: |
3043 次 |
最近记录: |