Angular 访问 ng-template 内部组件

10
假设我们有一个名为TopComponent的组件,其模板如下:
<ng-template #top>
    <inner-selector #inner></inner-selector>
</ng-template>

代码很简单:
//... imports ...

@Component({
  // selector, styles etc
})
export class TopComponent implements AfterViewInit {

  @ViewChild('top') topComp : NgbModal;
  // NgbModal is a type provided by some 3rd-party library
  // I can't modify it
  
  ngAfterViewInit() {
    // let's access the #inner component from here
  }
}

我可以使用这段代码访问#top组件:
@ViewChild('top') topComponent: TopComponent;

如何从同一类中访问 #inner 组件?
我尝试使用 @ContentChild('inner'),但仍然得到 undefined。
附注:作为一种解决方法,我可以创建另一个组件,在 中使用它,并从中访问所有必要的子组件。但是否可以以某种方式避免这种情况?

难道不应该是 @ViewChild('#top') 吗? - undefined
@Meir,你是指访问#top组件吗? 没有#符号也可以正常工作。 - undefined
2个回答

0
模板#top需要加载到某个容器中才能存在于DOM中,并被@ViewChild捕获。 最简单的方法是使用一个简单的结构指令。 在下面的示例中,NotReady是一个布尔值,在ngInit完成后将其设置为false。
<div *ngIf="notReady else top"> 
    loading... 
</div>
<ng-template #top>
    <inner-selector #inner></inner-selector>
</ng-template>

请注意,@ViewChild('top') 需要映射为 static:false,因为在 ngOnInit() 之后可能还不可用/存在。 每次变更检测周期都会搜索 #top,这在使用条件指令如 *ngIf 时非常有用。
//... imports ...

@Component({
  // selector, styles etc
})
export class TopComponent implements AfterViewInit {

  notReady: boolean = true;

  @ViewChild("top", { static: false })  topComp : NgbModal;
  // NgbModal is a type provided by some 3rd-party library
  // I can't modify it
  
  ngInit(){
    this.notReady = false;
  }

  ngAfterViewInit() {
    // let's access the #inner component from here
  }
}

-1

使用 descendants @ViewChild('inner', {descendants: true}) inner: InnerSelector;

这是完整的代码:https://plnkr.co/edit/MtVhHuAtPXZzC7GLOidF?p=preview

 @Component({
    selector: 'inner-selector',
    template:'inner-selector here'
  })
  export class InnerSelector {
    myVar = 0;
  }

  @Component({
    selector: 'my-app',
    template: `
      <div>
        <ng-template #top>
           <inner-selector #inner></inner-selector>
        </ng-template>

       <ng-container [ngTemplateOutlet]="top"></ng-container>
      </div>
    `,
  })
  export class App {
    @ViewChild('inner', {descendants: true}) inner: InnerSelector;
    constructor() {
      this.name = `Angular! v${VERSION.full}`
    }
    ngAfterViewInit() {
      console.log(this.inner);
    }
  }

4
这个例子似乎在没有使用“{descendants: true}”选项的情况下运作良好,这似乎是无效的配置。编译器会给出错误提示:类型为“{ descendants: boolean; }”的参数无法赋值给类型为“{ read?:any; }”的参数。对象文字只能指定已知属性,“descendants”不存在于类型“{ read?:any; }”中。 - undefined
3
即使没有 descendants: true,它也可以正常工作。重要的是使用 ngAfterViewInit 而不是 onInit 或构造函数。 - undefined
5
这对我不起作用,我得到了与@Algis相同的错误。即使没有……也无法工作。 - undefined
1
后代不再可用了吗? - undefined
@Tim 是的,主要的技巧是使用 ngAfterViewInit 而不是 ngOnInit。谢谢! - undefined
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接