angular5 - child component called before parent ngOnInit finish
Asked Answered
S

1

9

first, make table setting data in ngOnInit() and set to settingA variable.

this settingA variable binds to setting in html.

and I want to make table in child component using settingA.

but child component ngOnInit is called before parent component's ngOnInit finish.

so setting variable in child component is undefined.

I need your advice please.

This is parent component [grid-serialize.component.ts]

@Component({
    selector: 'grid-serialize',
    templateUrl: './grid-serialize.component.html',
    styles: []
})
export class GridSerializeComponent implements OnInit, OnChanges {
    tableSetting: TableSetting;
    settingA: TableSetting;
    rows: Bom[] = [];
    cols: ColumnSettings[] = [];
    userId: string;
    url: string;
    area: string;

    constructor(
        private router: Router,
        private tableService: TableService,
        private localStorageService: GridService
    ) {}

    ngOnInit(): void {

        this.userId = 'user01';

        this.url = this.router.url;

        const areaA = 'upper';
        const rowDataPathA = 'aaa/aaa/data.json';
        const columnDataPathA = 'bbb/bbb/column.json';
        const reorderableColumnsA = false;
        const resizableColumnsA = false;
        const paginatorA = true;
        const paginatorRowsA = 10;

        this.tableService.setColumnDataPath(columnDataPathA);
        this.tableService.setRowDataPath(rowDataPathA);
        this.tableService.getRowData().subscribe((rowData) => {
            console.log('---- getRowData() -----');
            this.rows = rowData;
            console.log('this.rows = ', this.rows);
            this.localStorageService
                .fetchColumns(this.userId, this.url, areaA)
                .subscribe((columnData) => {
                    if (columnData && columnData.length > 0) {
                        this.cols = columnData;
                        this.settingA = new TableSetting(
                            this.userId,
                            this.url,
                            areaA,
                            resizableColumnsA,
                            reorderableColumnsA,
                            this.cols,
                            this.rows,
                            paginatorA,
                            paginatorRowsA,
                            columnDataPathA
                        );
                    } else {
                        this.tableService
                            .getColumnSetting()
                            .subscribe((initData) => {
                                console.log('*** getColumnSetting() ***');
                                this.cols = initData;
                                console.log('this.cols = ', this.cols);
                                this.settingA = new TableSetting(
                                    this.userId,
                                    this.url,
                                    areaA,
                                    resizableColumnsA,
                                    reorderableColumnsA,
                                    this.cols,
                                    this.rows,
                                    paginatorA,
                                    paginatorRowsA,
                                    columnDataPathA
                                );
                            });
                    }
                });
            });
    }
}

settingA binds to setting variable in child component

This is parent component.html [grid-serialize.component.html]

<grid-table [setting]="settingA"></grid-table>

This is child component [table.component.ts]

@Component({
    selector: 'grid-table',
    templateUrl: './table.component.html',
    styles: []
})
export class TableComponent implements OnInit, OnDestroy {
    @ViewChild(Table) tableComponent: Table;
    @Input() setting: TableSetting;
    @Input() clickedEvent: string;

    area: string;
    paginatorRows: number;
    paginator: boolean;
    resizable: boolean;
    reordable: boolean;
    userId: string;
    msgs: Message[] = [];
    checkAll: Boolean = false;
    url: string;
    defaultCols: ColumnSettings[] = [];
    cols: ColumnSettings[] = [];
    rows: Bom[] = [];
    private subscription: Subscription;

    constructor(
    ) {}

    ngOnInit(): void {
        ⬇︎⬇︎⬇︎⬇︎⬇︎ this.setting is undefiend  ⬇︎⬇︎⬇︎⬇︎⬇︎
        console.log('this.setting = ', this.setting);
        this.tableComponent.reset();

        this.resizable = true;
        this.reordable = true;

        this.resizable = this.setting.resizableColumns;

        this.reordable = this.setting.reorderableColumns;

        this.paginator = this.setting.paginator;

        this.paginatorRows = this.setting.paginatorRows;

        this.service.setColumnDataPath(this.setting.columnDataPath);

        this.cols = this.setting.columnData;

        this.rows = this.setting.rowData;
    }
}

this is child component html [table.component.html]

<p-table [paginator]="paginator" [rows]="paginatorRows" [columns]="cols" [value]="rows" [resizableColumns]="resizable" [reorderableColumns]="reordable">
    <ng-container>
        <ng-container *ngTemplateOutlet="gridTableHeader"></ng-container>
    </ng-container>
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" pReorderableColumn pResizableColumn [ngStyle]="col.style" [pSortableColumn]="col.field">
                <span *ngIf="col.type === 'text'">
                    {{ col.caption | translate }}
                    <p-sortIcon [field]="col.field"></p-sortIcon>
                </span>
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowData let-columns="columns">
        <tr>
            <td *ngFor="let col of columns">
                <span *ngIf="col.type === 'text'">
                    {{ rowData[col.field] }}
                </span>
            </td>
        </tr>
    </ng-template>
</p-table>
Sarcous answered 21/2, 2018 at 16:43 Comment(1)
Angular loads everything at the same time. I would recommend adding an event emitterMagdalenmagdalena
T
23

You can add a *ngIf to check if its loaded, once the settingA value is available your child component will be rendered

<grid-table *ngIf="settingA" [setting]="settingA" [clickedEvent]="event"></grid-table>
Thermomotor answered 21/2, 2018 at 16:46 Comment(1)
Thank you very much!!!!!!!!!!!!!!!!!!!!!!!!!! I am so happy. its succeeded!! sorry for my english. I thank you once again.Merganser

© 2022 - 2024 — McMap. All rights reserved.