简体   繁体   中英

@Input() Not Passing As Expected Between Parent-Child Components in Angular 2 App

I am trying to abstract out a tabular-data display to make it a child component that can be loaded into various parent components. I'm doing this to make the overall app "dryer". Before I was using an observable to subscribe to a service and make API calls and then printing directly to each component view (each of which had the tabular layout). Now I want to make the tabular data area a child component, and just bind the results of the observable for each of the parent components. For whatever reason, this is not working as expected.

Here is what I have in the parent component view:

<div class="page-view">
    <div class="page-view-left">
        <admin-left-panel></admin-left-panel>
    </div>
    <div class="page-view-right">
        <div class="page-content">
            <admin-tabs></admin-tabs>
            <table-display [records]="records"></table-display>
        </div>
    </div>
</div>

And the component file looks like this:

import { API } from './../../../data/api.service';
import { AccountService } from './../../../data/account.service';
import { Component, OnInit, Input } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { TableDisplayComponent } from './../table-display/table-display.component';

@Component({
  selector: 'account-comp',
  templateUrl: 'app/views/account/account.component.html',
  styleUrls: ['app/styles/app.styles.css']
})
export class AccountComponent extends TabPage implements OnInit {

    private section: string;
    records = [];
    errorMsg: string;

    constructor(private accountService: AccountService,
                router: Router,
                route: ActivatedRoute) {
    }

    ngOnInit() {
       this.accountService.getAccount()
            .subscribe(resRecordsData => this.records = resRecordsData,
            responseRecordsError => this.errorMsg = responseRecordsError);
    }
}

Then, in the child component (the one that contains the table-display view), I am including an @Input() for "records" - which is what the result of my observable is assigned to in the parent component. So in the child (table-display) component, I have this:

import { AccountService } from './../../../data/account.service';
import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'table-display',
  templateUrl: './table-display.component.html',
  styleUrls: ['./table-display.component.less']
})
export class TableDisplayComponent {

    @Input() records;

    constructor() {
    }

}

Lastly, here's some of the relevant code from my table-display view:

<tr *ngFor="let record of records; let i = index;">
<td>{{record.name.first}} {{record.name.last}}</td>
                <td>{{record.startDate | date:"MM/dd/yy"}}</td>
                <td><a class="bluelink" [routerLink]="['/client', record._id ]">{{record.name.first}} {{record.name.last}}</a></td>

When I use it with this configuration, I get "undefined" errors for the "records" properties I'm pulling in via the API/database. I wasn't getting these errors when I had both the table display and the service call within the same component. So all I've done here is abstract out the table-display so I can use it nested within several parent components, rather than having that same table-display show up in full in every parent component that needs it.

What am I missing here? What looks wrong in this configuration?

You need to protect against record being null until it comes in to your child component (and therefore it's view).

Use Elvis operators to protect your template:

<tr *ngFor="let record of records; let i = index;">
    <td>{{record?.name?.first}} {{record?.name?.last}}</td>
    <td>{{record?.startDate | date:"MM/dd/yy"}}</td>
    <td><a class="bluelink" [routerLink]="['/client', record?._id ]">  {{record?.name?.first}} {{record?.name?.last}}</a></td>

You can also assign your input to an empty array to help with this issue:

@Input() records = [];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM