21

can someone please advice me how to read/bind attribute value to @component class, which seems to be undefined in ngOnInit method?

Here's a plunker demo: http://plnkr.co/edit/4FoFNBFsOEvvOkyfn0lw?p=preview

I'd like to read value of "someattribute" attribute

<my-app [someattribute]="'somevalue'">

inside the App class (src/app.ts) ngOninit method.

Thanks!

Tomino
  • 5,969
  • 6
  • 38
  • 50

3 Answers3

26

You can notice that such parameters can't be used for root component. See this question for more details:

The workaround consists in leveraging the ElementRef class. It needs to be injected into your main component:

constructor(elm: ElementRef) {
  this.someattribute = elm.nativeElement.getAttribute('someattribute'); 
}

We need to use the component this way in the HTML file:

<my-app someattribute="somevalue"></my-app>
Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Sorry, it was a typo. This doesn't work as well. Please see the plunker. – Tomino Feb 25 '16 at 13:01
  • No worries! I updated my answer... The problem is because you try to use this on the main component of your application (the one you use to bootstrap it) – Thierry Templier Feb 25 '16 at 13:04
  • Yes! That's it... I did not realized that I cannot use attributes in a root component. Can you please remove 'interpolation' part of your answer and keep just part below 'code'? Just to avoid confusion of users like me. – Tomino Feb 25 '16 at 13:07
  • This is a bad idea because of the security ricks and coupling to the DOM as noted in the API. https://angular.io/docs/js/latest/api/core/index/ElementRef-class.html use the @Input decorator – Michael Warner Feb 24 '17 at 21:47
  • The security risks pertain to DOM manipulation. If you read further into the security guide (https://angular.io/guide/security#direct-use-of-the-dom-apis-and-explicit-sanitization-calls) it's the ElementRef's `document` node that has unsafe methods. Simply reading attributes from a DOM element is not an inherit security risk. You can also use a third-party library like StencilJS which supports creating custom properties on components: https://stenciljs.com/docs/properties – TheLandolorien Aug 18 '19 at 15:13
18

You should use @Input decorator.

This is an example:

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

@Component({
    selector: 'user-menu',
    templateUrl: 'user-menu.component.html',
    styleUrls: ['user-menu.component.scss'],
})
export class UserMenuComponent {

    /**
     * userName Current username
     */
    @Input('userName') userName: string;

    constructor() {

    }
    sayMyName() {
        console.log('My name is', this.userName);
    }
}

And to use it

<user-menu userName="John Doe"></user-menu>
Sunil Garg
  • 14,608
  • 25
  • 132
  • 189
Germanaz0
  • 914
  • 8
  • 18
  • 1
    this is a much better approach than reading the getAttribute if not used on the root element – darwin Mar 20 '18 at 09:30
  • 1
    This must be accepted answer. A proper way to get attribute. – Rafique Mohammed Aug 30 '18 at 11:10
  • 3
    This answer doesn't address the issue with creating a custom attribute on a root component. While this solution is file for a parent/child component property binding, the accepted answer is correct for what the scenario (root component). – TheLandolorien Aug 18 '19 at 15:10
6

Update

Inputs aren't supported in the root component as a workaround you can use

constructor(elementRef:ElementRef) {
  console.log(elementRef.nativeElement.getAttribute('someattribute');
}

See also https://github.com/angular/angular/issues/1858

See also the fixed Plunker

original

You need to either use

[property]="value" 

or

property="{{value}}"

or if it's an attribute

[attr.property]="value" 

or

attr.property="{{value}}"
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567