Is there a safe way to create a Component or Directive that apply an encapsulated class to an input tag i.e. ?

my goal is to use the input tag with selector[attribute] instead of selector to avoid wrapping the input with a host component.

I prefer selector[attribute] over selector] to avoid reinventing the wheel i.e. if I want to support autocomplete, I have to use @Input() autocomplete: string = "" and then add it to the <com-input autocomplete='email'>

Expected usage

    <input
      com-input
      #inputEmail
      autocomplete="username"
      (input)="email = inputEmail.nativeElement.value"
      [isError]="errorMessage ? true : false"
      placeholder="Email"
      type="email"
    />

The problem is:

  1. when we add the attribute i.e. <input com-input> and then add a hash symbol i.e. <input com-input #inputElement>, the the inputElement type become InputComponent instead of HTMLInputElement. So, we can not access the input value.

The solution is:

  1. implement ElementRef<HTMLInputElement> and inject ElementRef to InputComponent. Then, set the nativeElement property.

However, Angular documentation warned that the ElementRef is not safe. So, I am pretty sure my work is a hack.

/* eslint-disable @angular-eslint/component-selector */
import { Component, ElementRef, HostBinding, Input } from '@angular/core';

@Component({
  selector: 'input[com-input]',
  standalone: true,
  imports: [],
  templateUrl: './input.component.html',
  styleUrl: './input.component.scss',
})
export class InputComponent implements ElementRef<HTMLInputElement> {
  nativeElement: HTMLInputElement;

  @HostBinding('class.error') @Input() isError: boolean = false;

  constructor(elementRef: ElementRef) {
    this.nativeElement = elementRef.nativeElement;
  }
}