0

I've created a component in my app that acts as a wrapper for an input tag (I'm making my own UI library for fun). My component would be used like so.

<sio-input [label]="'Sio Input Label'">
        <input type="text" name="">
</sio-input>

The point of this is to dynamically add CSS classes and functionality so the developer doesn't have to. Here is my component (I have really scaled down the code for readability)

@Component({
  selector: 'sio-input',
  templateUrl: './input.component.html', // only contains <ng-content></ng-content>
  styleUrls: ['./input.component.scss'],

})
export class InputComponent implements OnInit {

  @Input() label: string;
  // this component used Render2 - https://angular.io/api/core/Renderer2
  constructor(private elRef: ElementRef, private renderer: Renderer2) {
  }

  ngOnInit() {
    // if a label exist prepend it to the HTML
    if (this.label) {
      const formInput = this.elRef.nativeElement.querySelector('input');
      const appendLabel = this.renderer.createElement('LABEL');
      const textNode = this.renderer.createText(this.label);
      this.renderer.addClass(appendLabel, 'sio-input__label');
      this.renderer.appendChild(appendLabel, textNode);
      this.renderer.insertBefore(this.elRef.nativeElement, appendLabel, formInput);

      // add the directive
      this.renderer.setAttribute(formInput, 'sioInput', null);
    }
  }
}

@Directive({
  selector: '[sioInput]'
})
export class SioInputDirective {
  @HostListener('focus', ['$event.target'])
  onFocus(event) {
    console.log('Boom! We Have Focus');
  }
}

As you can see I wish to dynamically add an Attribute Directive to the formInput I find in the component's DOM. Sadly this doesn't work as the output rendered by renderer.setAttribute takes the 'sioInput' attribute name and renders it 'sioinput' so Angular doesn't recognise the Attribute Directive. Should I manually put the directive name in the template HTML on the input naturally everything works - but I want this to be dynamic. What am I doing wrong? How can I set the Attribute Directive dynamically without the name being converted to lowercase.

Many thanks in advance - if I haven't explained my problem well or it is confusing please say so and I shall reword my question.

1 Answer 1

0

Angular is a compiled language : you write TS, it transforms it to JS.

The selectors in the decorators are pre-build : they can not be applied post-build.

This means that you should not use the renderer (which will act post-build), but rather the template itself to manage your angular components.

As a sidenote, the directive in a component is usually a way for the component to use @ContentChild to manage the content through <ng-content>. Except from adding custom classes to the elementRef, and maybe implementing a control value accessor, the directive doesn't do much.

I suggest you take a look at Material Input Elements or PrimeNG to see how they do it, since they are widely used and generally very easy to use too !

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.