20

Maybe this is normal behavior, making a test, this.myColor It is undefined, but why? That mistake wrong in my code:

<h1 myDR [myColor]="red" > Test </h1>

import {Component, Directive, Input, ElementRef} from 'angular2/core';

@Directive({
    selector: '[myDR]',
    host:{
        '(mouseenter)' : ' mouseEnter()'
    }
})

export class MyDi {
    
    @Input () myColor: string;
    
    constructor(private el:ElementRef) {
        
    }
    
    mouseEnter(){
      
        this.el.nativeElement.style.backgroundColor = this.myColor;
    
        console.log(this.myColor);
     }
}

@Component({
    selector: 'my-app',
    template: `<h1>Hello World Angular2</h1> 
 
              <h1 myDR [myColor]="red" > Test </h1>
              `,
    directives: [MyDi]
})

export class App {
    constructor(){
        
    }
}

You can move the mouse over "Test" and look in the Console

Plunker

2 Answers 2

51

You have to enclose your input binding in simple quotes, like this

[myColor]="'red'"

This will bind the red string to myColor. If you remove the simple quotes it will look for a class property named red which doesn't exist therefore it returns undefined

You can do it as I mentioned above, or you can create a class property named red. In this case it will bind to the class property.

@Component({
    template: `<h1 myDR [myColor]="red" > Test </h1>`
})

export class App {
    red: string = 'red';
}

Edit

I forgot to mention that accessing the DOM through nativeElement is discouraged. You should use Renderer, @HostBinding or the host property in @Component (the last two are equivalent). So you have three more options

  • Using host property
@Directive({
    host:{
        '(mouseenter)' : ' mouseEnter()',
        '[style.background-color]' : 'myColor'
    }
})

mouseEnter(){
    this.myColor = 'blue';
}
  • Using @HostBinding (this case will set the color immediatly)
@HostBinding('style.background-color') get color {
    return this.myColor;
}

mouseEnter(){
    this.myColor = 'blue';
}
  • Using Renderer (use this instead of nativeElement.style = 'value')
constructor(public renderer: Renderer, public element: ElementRef) {}

mouseEnter(){
  this.renderer.setElementStyle(this.element.nativeElement, 'background-color', this.myColor);
}
Sign up to request clarification or add additional context in comments.

8 Comments

Ohh, it's true, I feel stupid now. thanks for your time.
@AngelAngel you're welcome. I updated my answer with something it may interest you.
its update is really useful, it is possible to adapt the title of my question to make it easier to access your answer with the information of the update, I think I could help others learn these ways
something like: @Input undefined Angular 2 using native Element, for example?
Eric and @AngelAngel, Eric's update would be good to put into another question, "What are some good alternatives to accessing the DOM using nativeElement?"
|
8

A simpler way for binding static text is

<h1 myDR myColor="red" > Test </h1>

See Angular2 documentation under "One-time string initialization".

Plunker

3 Comments

it is true, I had not thought, in that alternative thanks for your reply is good to keep in mind
Günter, this comment is for other readers (since we've had a good discussion about this in other comments): I don't really like this shorthand notation because it looks like just an HTML attribute. We have to examine the component definition to determine if myColor is an input property. If it is, then this syntax also populates the input property with the value red. If it isn't, then it is just an HTML attribute. I find that ambiguous. I much prefer to see the []s whenever we want to affect a directive or a component property. They immediately tell us that we're property binding.
@MarkRajcok Thanks for that explanation, I didn't understand the difference of using with [] and without [], and your explanation cleared it up. It is better to use with [] and set the value with a single quote inside a double quote string like [prop]=" 'literalValue' " because it is obvious that we are property binding, not just setting an HTML attribute. Also, this way it doesn't set that prop as an HTML attribute but rather it only creates a ng-reflect attribute.

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.