无法读取角度4中未定义的属性

时间:2018-02-03 14:23:04

标签: angular

我实现了@input并将对象详细信息从父级传递给子级。我在初始化子组件时收到以下错误。我在init方法上调用子组件上的方法来读取对象属性并填充对象。我怀疑在该方法中调用@input元素时没有初始化。我在NetPresentValueAnalysisComponent中的流程方法的第1行遇到错误。有时间滞后,它会被初始化。什么可以解决这个问题。

TypeError: Cannot read property 'captiveInsYear' of undefined

results.component.ts(父组件)

import { Component, OnInit } from '@angular/core';
import { RunService } from '@wtw/platform/services';
import { Base } from '@wtw/toolkit';
import * as BackendDto from '../../../api/dtos';
import * as BackendProxy from '../../../api/proxies';


    @Component({
      selector: 'app-results',
      templateUrl: './results.component.html'
    })
    export class ResultsComponent extends Base.ReactiveComponent implements OnInit {
      run: BackendDto.CaptivesRun;
      npvResults: BackendDto.NpvResults;


      sourceResults: BackendDto.NpvResults = {} as BackendDto.NpvResults;

      constructor(
        private _runService: RunService,

      ) {
        super();
      }

      ngOnInit() {

        this._subscriptions  =  [this._runService.activeRun.subscribe((r:  any)  =>  {
          this.run  =  r.data  as  BackendDto.CaptivesRun;

          // Initialising the data

          if  (this.run.strategies) {
            if (!this.run.strategies[0].results) {
              // TODO: push this down to the strategy container and ensure params are set for the strategy id
              this._runService.executeTrigger(r.runId, r.data, { number:  2, param:  ''  }, r.currencyInfo)
              .uiSignal('trigger 2')
              .subscribe(x  =>  {
                this.run  =  x.data;
               // console.log('t2 called');
                this.processResults(x.data.strategies[0].results);
              });
            } else {
               // console.log('t2 not called');
                this.processResults(this.run.strategies[0].results);
            }
          }

        })];

      }

      processResults(results: BackendDto.Results) {
        // TODO: observable results loaded for child components to subscribe to or even better move to a service
        this.npvResults  =  Object.assign({}  as  BackendDto.NpvResults, results.npvResult);

      }

    }

results.component.html

<div class="container-fluid mt-3 mb-3 test-feasibility--details">

<app-assumptions-summary></app-assumptions-summary>

<app-base-strategy></app-base-strategy>

<div class="row">
  <div class="col-12 test_feasibility--accordion">
        <!-- Accordion -->
        <div id="accordion" role="tablist">

          <app-net-present-value-analysis [NpvResults] = 'npvResults'></app-net-present-value-analysis>

        </div><!-- Accordion End -->
      </div>
  </div>
</div>

净现值-analysis.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { NpvResults, ModelingAssumption } from '../../../../api/dtos';
import { BoxPlotChartComponent } from "../../../../shared/HighCharts/box-plot-chart/box-plot-chart.component";
import { AssumptionsService } from '../../../../services/assumptions.service';
import { ReactiveComponent } from '@wtw/toolkit/src/utils/base.component';
import { DecimalPipe } from '@angular/common';

@Component({
  selector: 'app-net-present-value-analysis',
  templateUrl: './net-present-value-analysis.component.html',
})
export class NetPresentValueAnalysisComponent extends ReactiveComponent implements OnInit {

  isExpanded = false;
  showTable = true;
  showProjection = true;
  public yearList: number[] = [];
  public sum = (total, currentValue) => { 
    //console.log(currentValue);
    return total + currentValue;
  };


  currentYear = new Date();
  public toYear : number;
  //toYear1 = this.toYear.setFullYear(this.toYear.getFullYear() + 5);
  @Input() NpvResults: NpvResults = {} as NpvResults;



  constructor() {
    super();

  }

  ngOnInit() {
    console.log(this.NpvResults);
    // console.log(this.NpvResults[0].captiveDividentDistribution);
    // console.log(this.NpvResults.captiveDividentDistribution);
     this.processYears();

  }

  processYears(){

  let totalYears:any = this.NpvResults.captiveInsYear[this.NpvResults.captiveInsYear.length-1];

   for (var i = 0; i < totalYears; i++) 
    {
      if (i <= 6)
        {
          var val = this.currentYear.getFullYear() + i
          this.yearList.push(val);
        }

    }
       this.toYear = this.yearList[this.yearList.length - 1]

  }

}

2 个答案:

答案 0 :(得分:0)

这是因为NpvResults以异步方式加载到父组件中,因此当视图最初呈现时,NpvResults未定义。

您基本上使用 AfterViewChecked

export class NetPresentValueAnalysisComponent extends ReactiveComponent implements AfterViewChecked {

}

答案 1 :(得分:0)

由于您正在尝试处理由输入绑定属性发送的数据,因此要使用的良好模式是实现OnChanges。因此,您的子组件需要implement OnChanges。然后在实际实现中你可以有类似

的东西
ngOnchanges(changes: SimpleChanges): void {
    if(changes.NvpResults && changes.NvpResults.currentValue){
         this.processYears();
    } 
}

changes对象包含所有@Input绑定上发生的所有更改。通过具体检查NvpResults绑定更改时,您确保仅在可用时或实际发生更改时运行代码,并且在您有多个绑定时更有效。