2017-08-01 4 views
0

のプロパティを読み取ることができません:コンポーネントのTSファイルで定義された@Input複雑なオブジェクトは、エラーをスローすると、親コンポーネントに子コンポーネントにパラメータを渡す未定義

<app-conf-name 
    [inputName]='person.name' 
    (updatedNameEvent)='updateName($event)'> 
</app-conf-name> 

@Input() inputName: Names; 
@Output() updatedNameEvent: EventEmitter<Names> = new EventEmitter(); 
constructor() { } 
editName: Names = new Names(); 

ngOnInit() { 
    this.editName = this.inputName; 
} 

クラスでは、Names型がcorrectPersonフィールドのデフォルト値を設定します。

export class Names { 
    indivId: number; 
    firstName: string; 
    prefName: string; 
    lastName: string; 
    suffix: string; 
    updated: boolean = false; 
    correctPerson: boolean = false; 
    correctAsIs: boolean = false; 
    correctionDate: Date; 
    addedDate: Date; 
} 

は、なぜ私はこのエラーを取得しています:

ERROR TypeError: Cannot read property 'correctPerson' of undefined 
    at Object.View_ConfNameComponent_0._co [as updateDirectives] (ConfNameComponent.html:9) 
    at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13056) 
    at checkAndUpdateView (core.es5.js:12236) 
    at callViewAction (core.es5.js:12601) 
    at execComponentViewsAction (core.es5.js:12533) 
    at checkAndUpdateView (core.es5.js:12242) 
    at callViewAction (core.es5.js:12601) 
    at execComponentViewsAction (core.es5.js:12533) 
    at checkAndUpdateView (core.es5.js:12242) 
    at callViewAction (core.es5.js:12601) 

オブジェクトpersonが親コンポーネントに呼び出されたサービスから初期化されます。

親コンポーネント私は割り当てを経由して、エラーをもう一度投げるのプロパティを初期化してきました

person: Person = new Person(); 
constructor(private peopleService: PeopleService) { } 
state: string = 'one'; 
ngOnInit() { 
    this.peopleService.getPersonById(this.Id).subscribe((data)=>{ 
     this.person = data; 
     console.log(this.person); 
     this.person.name.correctPerson = false; 
     this.person.name.correctAsIs = false; 
     this.person.email.correctAsIs = false; 
     this.person.phone.correctAsIs = false; 
     this.person.address.correctAsIs = false; 
    }); 
} 

注意。

子コンポーネントの元のコードでは、入力変数が作業変数として使用されていました。

この質問に答えてプロジェクトの全面的な働きを試してみたところ、ngIfをどこに配置しても最終的な子コンポーネントが最後にエラーを投げかけていたことが分かりました。

はここにあなたがOnInitではなくOnChanges@Input()パラメータにアクセスするべきではない完全なGitHub Repo

+0

親コンポーネントのコードとperson.nameの解決方法を教えてください。 –

+0

をリクエストしてくださいJeanPaul –

答えて

2

へのリンクです。そのObservableと瞬間OnInitが発生するまで解決する保証はありません。

詳細については、こちらを見てみましょう: Angular 2/4 @Input only moves intrinsics - not lists or objects

+0

これを受け入れるのを延期するつもりです。間違いなくそれを読むでしょう。 –

+0

これは私の問題を解決しました。コンストラクタに注入するパラメータが必要なサービスを使用していました。私のコンポーネントの1つがそのサービスを使用し、ngOnInitの実行中にそのサービス内のいくつかの関数を呼び出しました。私は 'methodXXXをundefinedで呼び出す'というエラーを受け取りました。すべてのロジックを 'ngOnChanges'に移動すると、問題を解決するのに役立ちました。 Thanks @ dee-zg – Nicolas

0

上記のコードの問題は、サーバーへのコールが非同期であるということです。これは、子コンポーネントが作成された時点で、必ずしも名前が定義されているとは限りません。

  • 親コンポーネントが空の人物オブジェクトと、作成され、以下のように

    データの流れです。 (したがってpeople.nameが呼び出されたときに失敗することはありません。なぜなら、人々は決して定義されていないからです)。

  • initが実行されると、親コンポーネントは非同期チャレンジを行います。
  • initに続いて、子コンポーネントが作成されます(非同期呼び出しが終了するまで待機しません)。
  • 親オブジェクト(people)の名前が定義されていないため(子コンポーネントのhtmlで読み込まれている可能性があるため)、子コンポーネントは失敗します。

問題が2つ修正されています。最初は、第二の溶液

<app-conf-name 
    *ngIf='person.name' [inputName]='person.name' 
    (updatedNameEvent)='updateName($event)'> 
</app-conf-name> 

以下のように自分の子コンポーネントタグにngIfを追加することで、親コンポーネントが作成される前に、あなたのサービスからデータを解決する決意ガード、を利用することです。あなたのルート定義で

{ 
    path: 'your-path', component: YourParentComponent, 
    resolve: { 
    person: PersonResolveGuard 
    } 
} 

あなたの決意ガード

あなたの親コンポーネントで
@Injectable() 
export class BlockingResolveGuard implements Resolve<Person> { 

    constructor(private peopleService: PeopleService) {} 

    resolve(route: ActivatedRouteSnapshot):Observable<Person> { 
     // Call to service 
    } 
} 

、現在アクティブにルートを注入

constructor(private route:ActivatedRoute, private peopleService: PeopleService) { } 

とあなたのngOnInitで

()

ngOnInit() { 
    this.route.data.resolve((data:{person:Person}) => { 
     this.person = data.person; 
    } 
} 

この角度DOC:どのように警備員を解決する詳細な説明を与える(と他の警備員が働く)https://angular.io/guide/router#resolve-guard

注上記の溶液を用いて、あなたがからのデータを取得している人のIDを解決する必要があることリゾルブガードでactivatedRouterSnapshotを使用するルートパラメータ。

+0

ルータデータが非同期であるため、解決ガードでは問題は解決しません。 – cgTag

+0

route.dataオブジェクトは実際には観測可能ですが、データは既に解決されており、すぐに割り当てられます。詳細については、角度ガイドをお読みください。 –

+0

JeanPaulに感謝しますが、私はこのアプリケーションではルータを全く使用していません。これは小さすぎます。 ngIfを使用しているようです。 –

1

あなたはここで2つのことをしています。遅延データの読み込みとそのデータを親のngOnInitに読み込みます。したがって、子供の@Input()バインディングがundefinedであると想定する必要があります。

ngOnInitが実行される前に@ViewChildのプロパティが設定されていますが、後で@ContentChildが設定されるためです。これは、データがロードされる前に親コンポーネントのテンプレートがビューにレンダリングされ、そのテンプレートが子の@Input()バインディングにundefinedを渡していることを意味します。

Note: I hope the above is accurate. Haven't had my morning coffee yet.

いずれかの方法は、あなたが常にサポートは、コンポーネントのバインディングを欠落している必要があります。

@Input() inputName: Names; 
@Output() updatedNameEvent: EventEmitter<Names> = new EventEmitter(); 
constructor() { } 
editName: Names; 

ngOnInit() { 
    this.updateEditName(); 
} 

ngOnChanges(changes: SimpleChanges) { 
    if('inputName' in changes) { 
     this.updateEditName(); 
    } 
} 

private updateEditName() { 
     this.editName = this.inputName || new Names(); 
} 
+0

このSimpleChangesオブジェクトは何ですか? –

+0

これは 'OnChanges'インターフェースからのものです。 Angularは '@Input()'バインディングが変更されるたびに 'SimpleChanges'オブジェクトを渡します。 – cgTag

関連する問題