首页 文章

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

提问于
浏览
3

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

现在我在父组件中使用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);
    }
}

儿童组件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

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

    grid-header.component.ts

    export class GridHeaderItemComponent implements OnInit {
        public grid;
        @Input() name: string = '';
    
        constructor(private parent: GridHeaderComponent) { }
    

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

    grid-header.component.ts

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

    你也可以在 Plunker Example 看到它的实际效果

  • 1

    使用此解决方案,您将可以访问ngAfterViewInit中的数据,但您不会拥有“circural dependecy”(parent - > < - 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>
    <grid-header-item fxFlex name="Type"></grid-header-item>
    <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>`,
    })
    //...
    

相关问题