Luis Crespo
Luis Crespo

Reputation: 788

Angular 2: Accessing list of attributes from component definition

I am defining my own <input> component with label, layout, bootstrap classes, etc. So when I use it like this:

<my-input label="Street" [(ngModel)]="address.street"></my-input>

Then it will instantiate MyInputComponent, which will use a rich template to generate something like:

<div class="form-group">
    <label class="col-sm-3 control-label">{{ label }}</label>
    <div class="col-sm-9">
        <input [(ngModel)]="value" class="form-control">
    </div>
</div>`

This is working great and I can access the "label" attribute just by using @Input:

@Component({...})
export class MyInputComponent {
    @Input() label = '';

Now that is great for just a few attributes. But the HTML standard <input> tag has literally dozens of attributes such as type, min, max, placeholder... and I don't want to have to define every single possible attribute as an @Input property of MyInputComponent.

Instead, I want to dynamically iterate over the attributes in <my-input> and copy them to the <input> element inside my template. I know I can access the list of attributes of the DOM element by using ElementRef in the constructor and then accessing its nativeElement property:

constructor(eref: ElementRef) {
    console.log("***", eref.nativeElement);
}

But accessing nativeElement is discouraged as a bad practice for several reasons (see https://angular.io/docs/js/latest/api/core/index/ElementRef-class.html).

So the question is: is there some way to access the list of attributes of <my-input> without resorting to directly reading the native browser DOM?

And likewise, once I have the list of attributes in a neutral, non-native way, how can I then propagate them to the <input> tag inside my template?

Upvotes: 4

Views: 2943

Answers (1)

Lucas T&#233;treault
Lucas T&#233;treault

Reputation: 953

I think you would be better of using transclusion to wrap your input in your fancy MyInputComponent. Have a look at the follow blog:

https://toddmotto.com/transclusion-in-angular-2-with-ng-content

Essentially you would change this:

<my-input label="Street" [(ngModel)]="address.street"></my-input>

To this:

<my-input label="Street">
    <input [(ngModel)]="address.street"class="form-control">
</my-input>

So you could still access all the properties of input easily and get the decoration that you want with little work.

Upvotes: 2

Related Questions