typescript - Angular 2 : ngOnInit is called AFTER trying to render template when start from url with id

标签 typescript angular

我正在开发一个 Angular 应用程序,它使用从 AppComponent 链接到多个组件的路由器。这是 plunker 上的简化版本来说明这个问题(出于某种原因,完全相同的代码在本地运行但不在 plunker 上运行。)

当应用程序从 http://localhost:3000http://localhost:3000/home 启动时,链接 fruit1 fruit2 工作正常(点击导致 URL 更改为 http://localhost:3000/fruit/1 并带有描述文本)。然而,问题是当开始这个 url http://localhost:3000/fruit/1(输入这个 url 并回车)时,似乎 中的服务调用fruit-detail.component.tsngOnInit 在尝试呈现其 html 组件后被调用,这导致以下堆栈跟踪:

EXCEPTION: TypeError: Cannot read property 'description' of null in [ desc: {{fruit.description}}  in FruitDetailComponent@1:6]
angular2.dev.js:23925 EXCEPTION: TypeError: Cannot read property 'description' of null in [ desc: {{fruit.description}}  in FruitDetailComponent@1: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 在之后被调用的原因。那么,即使直接从“fruit/1”url 加载,如何拥有一个正常工作的应用程序呢?任何帮助表示赞赏!谢谢!

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

最佳答案

您可以为此使用 elvis 运算符:

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

实际上,调用this._foodService.getData() 是异步执行的,您在ngOnInit 方法返回后得到结果。

由于您使用路由,我认为 OnActivate 接口(interface)及其 routerOnActivate 方法正是您要寻找的。如果您在此方法中返回一个 promise ,组件将在更改路由之前等待 promise 得到解决。因此,当显示组件时,数据将在那里,您不会遇到这样的问题。

这是一个示例:

@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);
      })
    });
  }
}

有关详细信息,请参阅此链接:

关于typescript - Angular 2 : ngOnInit is called AFTER trying to render template when start from url with id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36759992/

相关文章:

typescript - Angular2 HTTP GET - 将响应转换为完整对象

Angular 2 : Update the iframe src when router url gets change

javascript - 实体元数据未找到 : No metadata for "User" was found

Angular 2 RC 5 路由器

typescript - 在 typescript 中使用 const 作为对象和类型?

typescript - 我们什么时候应该使用 Record<string, T> vs { [index : string]: T } ? [TypeScript

javascript - Angular 4,无法从函数的内部函数访问类的变量

node.js - ng 新给 "npm ERR! code EINTEGRITY required sha1 but found sha512"

angular - "@angular/http/index has no exported member of HTTP_PROVIDERS"

typescript - 导入 *.svg 模块引发 Typescript 错误 : "Cannot find module ..."