1

I want to insert dynamically attributes to an input html tag, but I don't know to to do this:

I've got this code from component side:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-transclusion',
  templateUrl: './transclusion.component.html',
  styleUrls: ['./transclusion.component.css']
})
export class TransclusionComponent implements OnInit {

  elements: any;

  constructor() { }

  ngOnInit() {
    this.elements = {};
    this.elements.name = 'TEST1';
    this.elements.type = 'text';
    this.elements.value = '12';
    this.elements.placeholder = 'PRUEBA';
    this.elements.maxlength = '10';

    // This is only for test elements keys
    for (const el in this.elements) {
      if (this.elements.hasOwnProperty(el)) {
        console.log(`${el}: ${this.elements[el]}`);
      }
    }
  }
}

And this is my template side:

<input  type="text"
        [attr.name]="elements.name"
        [attr.value]="elements.value"
        [attr.placeholder]="elements.placeholder"
        [attr.maxlength]="elements.maxlength"/>

I want any 'forin' like method to iterate over each elements attribute and insert dynamically on the input tag, so it results like this:

<input type="text"
       [attr.*for="el in elements"]="el"/>

How can I implement this?

Best Regards Antonio

Gab
  • 1,007
  • 9
  • 22
skormel
  • 33
  • 1
  • 1
  • 7
  • Possible duplicate of [How can I select an element in a component template?](https://stackoverflow.com/questions/32693061/how-can-i-select-an-element-in-a-component-template) – Gab Jan 27 '18 at 20:00

3 Answers3

2

If you want to dynamically change the attributes of a single <input> tag, I would recommend you use @ViewChild. For example,

import { Component, AfterViewInit, ElementRef } from '@angular/core';

@Component({
  selector: 'app-transclusion',
  template: `
    <input #foobar/>
    `,
  styleUrls: ['./transclusion.component.css']
})
export class TransclusionComponent implements AfterViewInit {

  @ViewChild('foobar') foobar: ElementRef;

  constructor() { }

  ngAfterViewInit() {
    this.foobar.nativeElement.value = 'foobar';
    // change other values of element
  }
}
Gab
  • 1,007
  • 9
  • 22
  • You're right I can access to that element using ElementRef but i'm working on a generic forms generator that supports sereval formcontrol types (input, dropdown, calendars, spinner, toggle button, etc) and I'll have to use so much viewchildren. Thanks for the information. – skormel Jan 27 '18 at 21:18
2

I've just solved it using this

import { Component, Renderer2, ElementRef, OnInit } from '@angular/core';

@Component({
  selector: 'app-transclusion',
  templateUrl: './transclusion.component.html',
  styleUrls: ['./transclusion.component.css']
})
export class TransclusionComponent implements OnInit {

  elements: any;

  constructor(private renderer: Renderer2, private el: ElementRef) { }

  ngOnInit() {
    this.elements = {};
    this.elements.name = 'TEST1';
    this.elements.type = 'text';
    this.elements.value = '12';
    this.elements.placeholder = 'PRUEBA';
    this.elements.maxlength = '10';

    const div = this.renderer.createElement('input');

    for (const el in this.elements) {
      if (this.elements.hasOwnProperty(el)) {
        this.renderer.setAttribute(div, el, this.elements[el]);
      }
    }
    this.renderer.appendChild(this.el.nativeElement, div);
  }

}

Thanks for all @nikolaus and @gab

skormel
  • 33
  • 1
  • 1
  • 7
1

You are following the wrong approach if you want to use attributes to "config" your input field you should use directives instad of a component...
and if you need to modify the native element on which you are appling your directive use the renderer service shipped with angular

Nickolaus
  • 4,785
  • 4
  • 38
  • 60
  • I've never used the renderer before, I'll study it and try to implement it with this, to avoid use directly ElementRef as recomended here https://stackoverflow.com/a/39785823/5283767 Thanks for all – skormel Jan 27 '18 at 21:21