4

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?

1 Answer 1

2

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.

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

3 Comments

Thank you, it looks great, I will read the article. I have heard about transclusion but never actually knew it was about this. Anyway I am still curious on whether there is a way to access attributes of Angular 2 components on a clean, neutral and non-native way.
I tried to use transclusion, but it is not enough because the transcluded input also requires some Bootstrap setup such as class="form-control". So either I force the user of my component to add such code every time, or I am back to having to manipulate the DOM to manually add the Bootstrap class.
P.S. I also tried <ng-content [ngClass]="{'form-control': true }"></ng-content>, but it had no effect whatsoever on the transcluded <input>.

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.