在呈现视图之前从父级设置子组件属性

时间:2017-06-12 15:29:17

标签: javascript angular typescript

我正在尝试在其视图呈现之前从其父级设置子组件属性。

现在我在父组件中使用ViewChildren装饰器,但在这种情况下为时已晚,因为子视图必须使用来自父组件的数据。

所以网格类保存了网格对象的完整引用,我想从grid-header绑定到grid-header-item。

Root html:

<grid-header [grid]="grid" [ngClass.xs]="{'search-open': grid.searchToggle, 'mobile-header': true}">
    <grid-header-item fxFlex="75px" name="Level"></grid-header-item>
    <grid-header-item fxFlex name="Type"></grid-header-item>
    <grid-header-item fxFlex name="Stats"></grid-header-item>
</grid-header>

父组件:

import { Component, ViewChildren, forwardRef, Input, OnInit, AfterViewInit, OnDestroy } from '@angular/core';

import { 
    StorageService, 
} from '../../_shared';

import { 
    GridHeaderItemComponent, 
} from './';

@Component({
    selector: 'grid-header',
    templateUrl: './grid-header.component.html',
    styleUrls: ['./grid-header.component.scss'],
    host: {'fxLayout': 'row'}
})
export class GridHeaderComponent implements OnInit, AfterViewInit {

    constructor(storage: StorageService) {}

    @Input() grid = null;
    @ViewChildren(forwardRef(() => GridHeaderItemComponent)) private headerItem;

    public ngOnInit() {

    }

    public ngAfterViewInit() {

        console.log(this.headerItem);

        setTimeout(() => {
            this.headerItem.grid = this.grid;
        }, 0);
    }
}

子组件:

import { Component, HostBinding, Input, OnInit, OnDestroy } from '@angular/core';

import { 
    StorageService, 
} from '../../_shared';

@Component({
    selector: 'grid-header-item',
    templateUrl: './grid-header-item.component.html',
    styleUrls: ['./grid-header-item.component.scss'],
    host: {

    }
})
export class GridHeaderItemComponent implements OnInit {
    public grid;

    constructor(storage: StorageService) {}

    @Input() name: string = '';

    public ngOnInit() {
        console.log(this.name);
    }

    public ngOnDestroy() {
        // this.storage.unsubscribeAll(this.class);
    }
}

child componetn html:

<span class="item" (click)="grid.onSortBy(name);">
    {{name}} <span *ngIf="grid.sort == name" class="fa" [ngClass]="grid.getDirection(name)"></span>
</span>

我知道,如果我将[grid] =“grid”添加到grid-header-item元素它可以工作,但我认为这是一个开销,因为所有的grid-header子节点都必须得到这个引用所以这是多余的

<grid-header [grid]="grid" [ngClass.xs]="{'search-open': grid.searchToggle, 'mobile-header': true}">
    <grid-header-item fxFlex="75px" [grid]="grid" name="Level"></grid-header-item>
    <grid-header-item fxFlex [grid]="grid" name="Type"></grid-header-item>
    <grid-header-item fxFlex [grid]="grid" name="Stats"></grid-header-item>
</grid-header>

2 个答案:

答案 0 :(得分:1)

由于angular2具有基于组件树的依赖注入系统,我们可以简单地在子组件中注入父组件实例:

<强>网格header.component.ts

export class GridHeaderItemComponent implements OnInit {
    public grid;
    @Input() name: string = '';

    constructor(private parent: GridHeaderComponent) { }

然后将parent.grid属性分配给ngOnInit中的本地grid属性

<强>网格header.component.ts

 public ngOnInit() {
   this.grid = this.parent.grid;
 }

您还可以在 Plunker Example

中查看它

答案 1 :(得分:0)

使用此解决方案,您可以访问ngAfterViewInit中的数据,但您不会拥有“circural dependecy”(parent-&gt;&lt; -child)。如果您需要更详细的通信,请尝试使用事件或共享服务。

<强> gridHeader.component.ts

@Component({
    selector: 'grid-header-item',
    template: `
        <span class="item" (click)="grid.onSortBy(name);">
            {{name}} <span *ngIf="grid.sort == name">Sortby</span>
        </span>
    `
})
export class GridHeaderItemComponent{
    @Input() name: string = '';
    public grid:any = {};
}

@Component({
    selector: 'grid-header',
    template:  `
    <grid-header-item fxFlex="75px" name="Level"></grid-header-item><br/>
    <grid-header-item fxFlex name="Type"></grid-header-item><br/>
    <grid-header-item fxFlex name="Stats"></grid-header-item>`
})
export class GridHeaderComponent implements AfterViewInit{   
  @ViewChildren(GridHeaderItemComponent) private headers:Array<headerItem>;   
  @Input() grid = {};
    ngAfterViewInit() {
      this.headers.forEach(h=>{//it can be a QueryList too
        h.grid=this.grid;
    });
}}

在网格的包装器组件中,你有这样的东西:

@Component({
  selector: 'my-app',
  template: `<grid-header [grid]="grid"></grid-header>`,
})
//...