Angular 如何从父组件查询ng内容的输入元素

Angular 如何从父组件查询ng内容的输入元素,angular,typescript,Angular,Typescript,创建如下所示的组件 <div class="test-search-field" [ngClass]="{'expanding': expanding}"> <ng-content></ng-content> </div> 我想从组件中获取此输入元素,但在使用@ContentChild进行查询时出错 @ContentChild('input') inputElemRef: ElementRef; ngAfterContentInit

创建如下所示的组件

<div class="test-search-field"
  [ngClass]="{'expanding': expanding}">
  <ng-content></ng-content>
</div>
我想从组件中获取此输入元素,但在使用
@ContentChild
进行查询时出错

@ContentChild('input') inputElemRef: ElementRef;

  ngAfterContentInit() {
    setInterval(() => {
      console.log(this.inputElemRef);
    }, 2000);
但是这个
inputElemRef
总是没有定义


谁能告诉我我在这里犯了什么错误。

我会用渲染器来做这件事

像这样的东西

ngAfterViewInit() {
  const el = this.renderder.selectRootElement('input');
  console.log(el);
}
  • 通过指令类标记进行查询
  • my-input.directive.ts

    import { Directive } from '@angular/core';
    
    @Directive({
      selector: '[myInput]',
    })
    export class MyInputDirective  {}
    
    my-input-container.component.ts

    import { Component, Input, ContentChild, AfterContentInit, ElementRef } from '@angular/core';
    import { MyInputDirective } from './my-input.directive';
    
    @Component({
      selector: 'my-input-container',
      template: `<ng-content></ng-content>`,
      styles: [`h1 { font-family: Lato; }`]
    })
    export class MyInputContainerComponent implements AfterContentInit {
      @ContentChild(MyInputDirective, { read: ElementRef }) child: MyInputDirective;
    
      ngAfterContentInit() {
        console.log(this.child);
      }
    }
    
    从'@angular/core'导入{Component,Input,ContentChild,AfterContentInit,ElementRef};
    从“./my input.directive”导入{MyInputDirective};
    @组成部分({
    选择器:“我的输入容器”,
    模板:``,
    样式:[`h1{font-family:Lato;}`]
    })
    导出类MyInputContainerComponent在ContentInit之后实现{
    @ContentChild(MyInputDirective,{read:ElementRef})child:MyInputDirective;
    ngAfterContentInit(){
    console.log(this.child);
    }
    }
    
    用法:

    <my-input-container>
      <input myInput />
    </my-input-container>
    
    <my-input-container>
      <input #myInput />
    </my-input-container>
    
    
    

  • 按模板变量进行查询
  • 如果只关心ElementRef,则可以完全跳过自定义指令,改为使用模板变量进行查询

    my-input-container.ts

    import { Component, Input, ContentChild, AfterContentInit, ElementRef } from '@angular/core';
    
    @Component({
      selector: 'my-input-container',
      template: `<ng-content></ng-content>`,
      styles: [`h1 { font-family: Lato; }`]
    })
    export class MyInputContainerComponent {
      @ContentChild('myInput') child: ElementRef;
    
      ngAfterContentInit() {
        console.log(this.child);
      }
    }
    
    从'@angular/core'导入{Component,Input,ContentChild,AfterContentInit,ElementRef};
    @组成部分({
    选择器:“我的输入容器”,
    模板:``,
    样式:[`h1{font-family:Lato;}`]
    })
    导出类MyInputContainerComponent{
    @ContentChild('myInput')子元素:ElementRef;
    ngAfterContentInit(){
    console.log(this.child);
    }
    }
    
    用法:

    <my-input-container>
      <input myInput />
    </my-input-container>
    
    <my-input-container>
      <input #myInput />
    </my-input-container>
    
    
    

    一般来说,第一个选项是首选选项,它是
    @angular/material
    对其输入组件所做的。它们将容器组件(
    matformfield
    )与应用于本机输入元素(
    matInput
    )的指令配对

    它更灵活,因为您可以查询指令或ElementRef

    @ContentChild(MyInputDirective)子级:MyInputDirective


    @ContentChild(MyInputDirective,{read:ElementRef})child:MyInputDirective

    这是一种有点奇怪的方法。为什么不把一个指令放在自己的输入元素上呢?是的,你们是对的,但不知何故,我无法更改这个现有的代码。若你们也要把一个指令放在输入元素上,那个么你们可以让那个指令将自己注册到一个注入到我的输入容器元素级别的服务中。例如,深入研究angular的代码,并尝试了解fromControlName属性如何知道它所在的formControlGroup。或者,看看Thomasz的答案…@Davy你能从我可以看到
    formControlName
    的链接吗?是的,这会有用的。但如果您能告诉我
    @ContentChild
    是否有效,我将不胜感激。还有,我们可以使用什么类型的查询?我相信
    @ContentChild
    只适用于指令(和元素)。如果元素可以工作,那么我在代码中犯了什么错误?元素是角度元素,而不是HTML标记。哦。。。谢谢你的澄清,这是正确的。但是如果你能说出
    @ContentChild
    的用途,那就太好了?它接受的查询类型是对转置内容的查询。我将用更多信息编辑我的帖子。给我一分钟。非常感谢你的时间和帮助。我认为@ContentChild是查询选择器的替代品,或者是人们所说的方式。我同意这个指令是更干净的方式