Angular2 - ContentChild查询找不到嵌套组件

时间:2016-06-27 17:59:45

标签: typescript angular

我正在尝试设置一个Angular2组件,该组件自动聚焦通过内容投影插入的输入元素。

我使用的解决方案基于this answer。我有一个额外的要求,即input元素可能嵌套在另一个组件中。但是,我发现ContentChild查询无法检测隐藏在ng-content标记内的元素。

@Component({
  selector: 'inner-feature',
  template: "<input auto-focus>",
  directives: [AutoFocus]
})
export class InnerFeature { }

@Component({
  selector: 'feature',
  template: `
    <div [class.hide]="!show">
      <ng-content></ng-content>
    </div>
  `
})
export class Feature {
  @ContentChild(AutoFocus)
  private _autoFocus: AutoFocus;

  private _show: boolean = false;

  @Input()
  get show() {
    return this._show;
  }
  set show(show: boolean) {
    this._show = show;
    if (show && this._autoFocus) {
      setTimeout(() => this._autoFocus.focus());
    }
  }
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <button (click)="toggleFeature()">Toggle</button>
      <feature [show]="showFeature">
        <inner-feature></inner-feature>
      </feature>
    </div>
  `,
  directives: [Feature, InnerFeature]
})
export class App {
  showFeature: boolean = false;

  toggleFeature() {
    this.showFeature = !this.showFeature;
  }
}

永远不会填充_autoFocus属性。与auto-focus指令没有嵌套在另一个组件中并且工作正常的情况形成对比。有没有办法使这项工作?

(我没有粘贴AutoFocus的代码,因为它对此示例并不重要。)

请参阅Plunker了解演示。

上面的

更新代码修复了缺失的指令。

2 个答案:

答案 0 :(得分:4)

ContentChildren设置为descendants

的情况下使用true
@ContentChildren(AutoFocus, { descendants: true })

答案 1 :(得分:2)

实际上我想在这个问题上花更多的时间来寻找更好的解决方案,但是现在我想出了以下可能对你有所帮助:

首先,您必须使用AutoFocusInnerFeatures内公开AutoFocus(并且忘记将directives添加到@ViewChild数组中)。这看起来像这样:

@Component({
  selector: 'inner-feature',
  template: "<input auto-focus>",
  directives: [AutoFocus]
})
export class InnerFeature {
  @ViewChild(AutoFocus)
  autoFocus:AutoFocus;
}

然后在您的父组件Feature中,您可以使用@ContentChildren返回绑定组件的QueryList(在您的情况下为InnerFeature)。

show方法中(或在ngAfterContentInit之内或之后),您可以访问此InnerFeatures列表:

export class Feature implements OnInit {
  @ContentChild(AutoFocus)
  private _autoFocus: AutoFocus;

  @ContentChildren(InnerFeature)
  private _innerFeatures: QueryList<InnerFeature>;

  private _show: boolean = false;

  @Input()
  get show() {
    return this._show;
  }
  set show(show: boolean) {
    this._show = show;
    if (show) {
      setTimeout(() => {
            if (this._autoFocus) {
                this._autoFocus.focus();
            }
            if (this._innerFeatures) {
                this._innerFeatures.map((innerFeature) => {
                    innerFeature.autoFocus.focus();
                });
            }
        });
    }
  }

  ngAfterContentInit() {
    console.log(this._autoFocus);
    console.log(this._innerFeatures);
  }
}

我修改了您的plunker,因此您可以对其进行测试。

可能不像你想要的那样充满活力,但是,我希望无论如何它都会有所帮助。

如果在英格兰与岛屿比赛之后没有更好的答案,我会尝试提出一个更好的方法;)

更新:我更新了我的代码,因为它在访问私有的_results时引发了错误。使用map()代替QueryList