What is the best way to access the input element of ng-content from the parent component?

Creating a unique component in the following structure

<div class="custom-search-field"
  [ngClass]="{'expanding': expanding}">
  <ng-content></ng-content>
</div>

When using this component, users are expected to include an input element within it.

<my-input-container>
    <input type="search" placeholder="Search">
</my-input-container>

The goal is to access this input element from within the component by using @ContentChild, but encountering errors while doing so.

@ContentChild('input') inputElemRef: ElementRef;

  ngAfterContentInit() {
    setInterval(() => {
      console.log(this.inputElemRef);
    }, 2000);

However, the inputElemRef always returns undefined.

If anyone can provide insight into what might be causing this issue, it would be greatly appreciated.

Answer №1

  1. Retrieve information using the directive class token.

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);
  }
}

usage:

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

Live demonstration

  1. Access data through the template variable.

If you are only interested in the ElementRef, you can disregard the custom directive and query by the template variable instead.

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);
  }
}

usage:

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

Live demonstration

In general, the preferred choice is the first option as seen with @angular/material and their input component. They pair the container component (mat-form-field) with a directive applied to the native input element (matInput).

This method offers more flexibility since you can query either for the Directive or for the ElementRef.

@ContentChild(MyInputDirective) child: MyInputDirective;

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

Answer №2

To achieve that, I would have used the renderer component.

Here is an example of how it could be done: stackblitz

ngAfterViewInit() {
  const element = this.renderer.selectRootElement('input');
  console.log(element);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with `rxjs/Subject.d.ts`: The class `Subject<T>` is incorrectly extending the base class `Observable<T>`

I found a sample template code in this helpful tutorial and followed these two steps to get started - npm install // everything went smoothly, created node_modules folder with all dependencies npm start // encountered an error as shown below- node_mo ...

Error: Unable to access 'match' property of an undefined value

After upgrading my Angular application from version 12 to 13, I encountered an error during unit testing. Chrome Headless 94.0.4606.61 (Windows 10) AppComponent should create the app FAILED TypeError: Cannot read properties of undefined (reading &a ...

There is no corresponding version available for [email protected] in Angular 6

After cloning a project from git, I attempted to run npm install. However, an error message popped up, as shown in the following link: https://i.stack.imgur.com/pqYbK.png Can someone please explain why this is happening and how I can resolve it? Any help ...

How can one access DOM elements (getting and setting values) that are nested within an *ngFor loop?

How can I access the <span> and <select> elements in my code template shown below? <div *ngFor="---"> <div> <span></span> <select> <option></option> <option></option> ...

Unable to retrieve HTTP call response during debugging, although it is visible in the browser

When I send an HTTP request to create a record, I am able to see the added record id in the Network section of browsers like Chrome and Firefox. However, when I try to debug the code and retrieve the same id value, I encounter difficulties. I have tried us ...

When initialized within an object, Angular may identify a field as undefined

Whenever I attempt to access a property of the object named "User," it shows up as undefined. However, upon logging the complete object to the console, the field appears with the necessary data. Here is the console log output: perfil.component.ts:42 unde ...

The JSX component cannot use 'Router' as a valid element

Error Message The error message states that 'Router' cannot be used as a JSX component because its return type 'void' is not a valid JSX element. TS2786 import App from './App'; 5 | > 6 | ReactDOM.render(<Router ...

Achieving automatic checkbox selection in Angular 6 through passing a value from one component to another

My page named second.html contains the following code: <div class="col-lg-4 col-md-4 col-sm-4"> <input type="checkbox" class="checkmark" name="nond" [checked]="r=='true'" (change)="nond($event, check)"> ...

Combining Angular 2 with CORS and incorporating a Spring Boot Rest Controller integrated with Spring Security

My application was functioning correctly using angular2 for the front end and spring boot rest controller. However, after incorporating spring security, I encountered an issue where functions with parameters in the spring boot rest controller were not bein ...

What could be causing my Vue code to behave differently than anticipated?

There are a pair of components within the div. When both components are rendered together, clicking the button switches properly. However, when only one component is rendered, the switch behaves abnormally. Below is the code snippet: Base.vue <templa ...

Replace interface with a string

Is it possible to override an interface with a string in TypeScript? Consider this example: type RankList = "Manager" | "Staff" interface EmployeeList { id: string, name: string, department: string, rank: "Staff&q ...

Error in Prisma: Unable to retrieve data due to undefined properties (attempting to access 'findMany')

Recently, I've been working on a dashboard app using Prisma, Next.js, and supabase. Encountering an issue with the EventChart model in schema.prisma, I decided to create a new model called EventAreaChart. However, after migrating and attempting to ex ...

What's the best way to reset the `react-google-recaptcha` checkbox in a redux application following the submission of a form?

My Redux application consists of two files: LoginForm (which contains the form elements) and LoginFormContainer (which manages form values using Formik). I am facing an issue with resetting the captcha, as the ref is located in the LoginForm file. I attemp ...

Routing static pages in Angular 2

I successfully created a static page using Angular 2. When I run ng serve and visit my page, it functions as intended. Specifically, I can navigate to a specific page by typing in the URL, such as www.mysite.com/resume. However, after uploading it to my si ...

Select the location for rendering the application within the root HTML using Single-SPA

I am strategizing to utilize the single-SPA framework alongside angular in order to construct a microfrontend architecture for a website. The current setup of the website is based on a legacy monolith structure, but we are aiming to transition it into a mi ...

Guide to setting up Cosmos DB database connection using NestJS version 9.0.0

I'm encountering issues when attempting to include the Cosmos DB connection module in nestjs v9, as I'm facing dependency errors. Nest is unable to resolve the dependencies of the AzureCosmosDbCoreModule (COSMOS_DB_CONNECTION_NAME, ?). Please ens ...

Using Angular 2 to Bind a Single Click Event to Multiple Elements

Within the component's export class, I have defined iconCheck: string;. In the constructor, I set this.iconCheck = "add_circle";. Additionally, in the export class, I have the following method: iconChange() { if(this.iconCheck == "add_circle") { ...

Utilizing custom types in React with TypeScript and Prop-Types

Currently, I am working with a string type literal that looks like this: type MyType = 'str1' | 'str2' | 'str3'. I need one of my props to only accept this specific type, but I'm struggling to specify this in PropTypes. ...

directive for a custom loader in ag-grid

I have incorporated ag-grid-angular into my project more than 20 times across different pages. Each time, I use a custom loader before the data is loaded. However, I would like to make this custom loader a directive so that it can be easily reused in all i ...

Mapping arrays from objects using Next.js and Typescript

I am trying to create a mapping for the object below using { ...product.images[0] }, { ...product.type[0] }, and { ...product.productPackages[0] } in my code snippet. This is the object I need to map: export const customImage = [ { status: false, ...