Angular 2:ngOnInit被称为尝试呈现模板时,从url开始使用id

Angular 2:ngOnInit被称为尝试呈现模板时,从url开始使用id

问题描述:

我正在使用一个角度的应用程序,它使用链接到多个组件AppComponent的路由器。这里是plunker一个简化版本来说明问题(因为某些原因,完全相同的代码在本地而不是运行在plunker。)Angular 2:ngOnInit被称为尝试呈现模板时,从url开始使用id

当应用程序从http://localhost:3000http://localhost:3000/home,链接fruit1fruit2工作正常(点击开始导致URL更改为http://localhost:3000/fruit/1与描述文本)。然而,问题是,当这个URL http://localhost:3000/fruit/1(键入这个URL并按回车键)开始时,似乎fruit-detail.component.tsngOnInit内的服务调用被称为AFTER试图呈现其html组件,这导致下面的堆栈跟踪:

EXCEPTION: TypeError: Cannot read property 'description' of null in [ desc: {{fruit.description}} in [email protected]:6] 
angular2.dev.js:23925 EXCEPTION: TypeError: Cannot read property 'description' of null in [ desc: {{fruit.description}} in [email protected]:6]BrowserDomAdapter.logError @ angular2.dev.js:23925BrowserDomAdapter.logGroup @ angular2.dev.js:23936ExceptionHandler.call @ angular2.dev.js:1320(anonymous function) @ angular2.dev.js:12857schedulerFn @ angular2.dev.js:13264SafeSubscriber.__tryOrUnsub @ Rx.js:10775SafeSubscriber.next @ Rx.js:10730Subscriber._next @ Rx.js:10690Subscriber.next @ Rx.js:10667Subject._finalNext @ Rx.js:11191Subject._next @ Rx.js:11183Subject.next @ Rx.js:11142EventEmitter.emit @ angular2.dev.js:13245NgZone._zoneImpl.ng_zone_impl_1.NgZoneImpl.onError @ angular2.dev.js:13666NgZoneImpl.inner.inner.fork.onHandleError @ angular2.dev.js:2143ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runGuarded @ angular2-polyfills.js:300NgZoneImpl.runInner @ angular2.dev.js:2155NgZone.run @ angular2.dev.js:13749(anonymous function) @ angular2.dev.js:12956schedulerFn @ angular2.dev.js:13264SafeSubscriber.__tryOrUnsub @ Rx.js:10775SafeSubscriber.next @ Rx.js:10730Subscriber._next @ Rx.js:10690Subscriber.next @ Rx.js:10667Subject._finalNext @ Rx.js:11191Subject._next @ Rx.js:11183Subject.next @ Rx.js:11142EventEmitter.emit @ angular2.dev.js:13245NgZone._checkStable @ angular2.dev.js:13689NgZone._zoneImpl.ng_zone_impl_1.NgZoneImpl.setMicrotask @ angular2.dev.js:13660NgZoneImpl.inner.inner.fork.onHasTask @ angular2.dev.js:2135ZoneDelegate.hasTask @ angular2-polyfills.js:449ZoneDelegate._updateTaskCount @ angular2-polyfills.js:466ZoneDelegate.invokeTask @ angular2-polyfills.js:427Zone.runTask @ angular2-polyfills.js:320drainMicroTaskQueue @ angular2-polyfills.js:541ZoneTask.invoke @ angular2-polyfills.js:493 
angular2.dev.js:23925 ORIGINAL EXCEPTION: TypeError: Cannot read property 'description' of nullBrowserDomAdapter.logError @ angular2.dev.js:23925ExceptionHandler.call @ angular2.dev.js:1329(anonymous function) @ angular2.dev.js:12857schedulerFn @ angular2.dev.js:13264SafeSubscriber.__tryOrUnsub @ Rx.js:10775SafeSubscriber.next @ Rx.js:10730Subscriber._next @ Rx.js:10690Subscriber.next @ Rx.js:10667Subject._finalNext @ Rx.js:11191Subject._next @ Rx.js:11183Subject.next @ Rx.js:11142EventEmitter.emit @ angular2.dev.js:13245NgZone._zoneImpl.ng_zone_impl_1.NgZoneImpl.onError @ angular2.dev.js:13666NgZoneImpl.inner.inner.fork.onHandleError @ angular2.dev.js:2143ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runGuarded @ angular2-polyfills.js:300NgZoneImpl.runInner @ angular2.dev.js:2155NgZone.run @ angular2.dev.js:13749(anonymous function) @ angular2.dev.js:12956schedulerFn @ angular2.dev.js:13264SafeSubscriber.__tryOrUnsub @ Rx.js:10775SafeSubscriber.next @ Rx.js:10730Subscriber._next @ Rx.js:10690Subscriber.next @ Rx.js:10667Subject._finalNext @ Rx.js:11191Subject._next @ Rx.js:11183Subject.next @ Rx.js:11142EventEmitter.emit @ angular2.dev.js:13245NgZone._checkStable @ angular2.dev.js:13689NgZone._zoneImpl.ng_zone_impl_1.NgZoneImpl.setMicrotask @ angular2.dev.js:13660NgZoneImpl.inner.inner.fork.onHasTask @ angular2.dev.js:2135ZoneDelegate.hasTask @ angular2-polyfills.js:449ZoneDelegate._updateTaskCount @ angular2-polyfills.js:466ZoneDelegate.invokeTask @ angular2-polyfills.js:427Zone.runTask @ angular2-polyfills.js:320drainMicroTaskQueue @ angular2-polyfills.js:541ZoneTask.invoke @ angular2-polyfills.js:493 
angular2.dev.js:23925 ORIGINAL STACKTRACE:BrowserDomAdapter.logError @ angular2.dev.js:23925ExceptionHandler.call @ angular2.dev.js:1332(anonymous function) @ angular2.dev.js:12857schedulerFn @ angular2.dev.js:13264SafeSubscriber.__tryOrUnsub @ Rx.js:10775SafeSubscriber.next @ Rx.js:10730Subscriber._next @ Rx.js:10690Subscriber.next @ Rx.js:10667Subject._finalNext @ Rx.js:11191Subject._next @ Rx.js:11183Subject.next @ Rx.js:11142EventEmitter.emit @ angular2.dev.js:13245NgZone._zoneImpl.ng_zone_impl_1.NgZoneImpl.onError @ angular2.dev.js:13666NgZoneImpl.inner.inner.fork.onHandleError @ angular2.dev.js:2143ZoneDelegate.handleError @ angular2-polyfills.js:394Zone.runGuarded @ angular2-polyfills.js:300NgZoneImpl.runInner @ angular2.dev.js:2155NgZone.run @ angular2.dev.js:13749(anonymous function) @ angular2.dev.js:12956schedulerFn @ angular2.dev.js:13264SafeSubscriber.__tryOrUnsub @ Rx.js:10775SafeSubscriber.next @ Rx.js:10730Subscriber._next @ Rx.js:10690Subscriber.next @ Rx.js:10667Subject._finalNext @ Rx.js:11191Subject._next @ Rx.js:11183Subject.next @ Rx.js:11142EventEmitter.emit @ angular2.dev.js:13245NgZone._checkStable @ angular2.dev.js:13689NgZone._zoneImpl.ng_zone_impl_1.NgZoneImpl.setMicrotask @ angular2.dev.js:13660NgZoneImpl.inner.inner.fork.onHasTask @ angular2.dev.js:2135ZoneDelegate.hasTask @ angular2-polyfills.js:449ZoneDelegate._updateTaskCount @ angular2-polyfills.js:466ZoneDelegate.invokeTask @ angular2-polyfills.js:427Zone.runTask @ angular2-polyfills.js:320drainMicroTaskQueue @ angular2-polyfills.js:541ZoneTask.invoke @ angular2-polyfills.js:493 
angular2.dev.js:23925 TypeError: Cannot read property 'description' of null 
    at AbstractChangeDetector.ChangeDetector_FruitDetailComponent_0.detectChangesInRecordsInternal (viewFactory_FruitDetailComponent:30) 
    at AbstractChangeDetector.detectChangesInRecords (angular2.dev.js:9689) 
    at AbstractChangeDetector.runDetectChanges (angular2.dev.js:9672) 
    at AbstractChangeDetector._detectChangesInViewChildren (angular2.dev.js:9751) 
    at AbstractChangeDetector.runDetectChanges (angular2.dev.js:9676) 
    at AbstractChangeDetector._detectChangesContentChildren (angular2.dev.js:9745) 
    at AbstractChangeDetector.runDetectChanges (angular2.dev.js:9673) 
    at AbstractChangeDetector._detectChangesInViewChildren (angular2.dev.js:9751) 
    at AbstractChangeDetector.runDetectChanges (angular2.dev.js:9676) 
    at AbstractChangeDetector.detectChanges (angular2.dev.js:9661) 

然后,这是记录到控制台,这就是为什么我怀疑ngOnInit后调用。那么,即使直接从'水果/ 1'网址直接加载,如何有一个工作的应用程序?任何帮助表示赞赏!谢谢!

===== extract data called!! 
fruit-detail.component.ts:25 got fruit inside fruitComponent !apple 

您可以使用Elvis操作符此:

<h2> desc: {{fruit?.description}} </h2> 

事实上,呼叫this._foodService.getData()异步执行,你会得到ngOnInit方法返回后的结果。

由于您使用路由,我认为OnActivate接口和它的routerOnActivate方法是您正在寻找。如果您在此方法中返回承诺,则组件将在更改路由之前等待承诺解决。所以当组件显示时,数据会在那里,你不会有这样的问题。

这里有一个例子:

@Component({ 
    (...) 
}) 
export class FruitDetailComponent implements OnInit, OnActivate { 
    fruit = null; 

    constructor(
    private _rbacService: FoodService, 
    private _routeParams: RouteParams) {} 

    routerOnActivate(next: ComponentInstruction, 
        prev: ComponentInstruction) { 
    return new Promise(resolve => { 
     let id = +this._routeParams.get('id'); 
     console.log('on init fruit component: id = '+id); 
     //get read write roles 
     this._rbacService.getData().subscribe(data =>{ 
     this.fruit = data['fruits'].filter(obj => obj.id === id)[0]; 
     console.log('got fruit inside fruitComponent '+this.fruit.description); 
     resolve(null); 
     }) 
    }); 
    } 
} 

请参阅此链接了解详情:

+0

感谢您的答复!有趣的是,使用第二个选项('OnActivate')不起作用;仍然有同样的错误。但是猫王操作员可以做到这一点!那么,对于elvis算子来说,事实上,最初被评估为null的变量会在以后再次被评估吗?有没有办法在模板内的任何地方打开“猫王模式”?这是一个拖动不得不添加'?'在每个变量之后。谢谢! – totoro

+0

事实上,你可以从'onActivate'方法返回一个承诺,这里是超级有用的部分。 – jcroll