2

I am trying to pass a value to the directive's custom attribute, but when I try to log it it says it is undefined.

This is my component.html:

<div appRadialMenu [step]="4"></div>

This is my directive.ts:

import { Directive, ElementRef, Input, OnInit } from '@angular/core';

// jQuery
import * as $ from 'jquery';

@Directive({
  selector: '[appRadialMenu]'
})
export class RadialMenuDirective implements OnInit {
  @Input() step;

  constructor(private elRef: ElementRef) {
      $(elRef.nativeElement).click(function () {
          console.log(this.step);
      }
  }
  ngOnInit() {
      console.log(this.step);
  }
}

Edit: I also tried using

@Input('step') step;

Edit 2: Thank you guys, it worked and I made the following changes:

I changed the click event binding and I moved it to the ngOnInit, also I changed the selector

selector: 'appRadialMenu'
// ......
@Input('step') step;

constructor(private elRef: ElementRef) {}

ngOnInit() {
    $(this.elRef.nativeElement).click(() => {
        console.log(this.step);
    });
}

component.html:

<appRadialMenu [step]="4"></appRadialMenu>
4
  • Possible duplicate of How to access the correct `this` inside a callback? Commented Sep 18, 2018 at 16:58
  • 1
    Use an arrow function as the callback: .click(() => { ... }). More importantly, avoid using jQuery for event binding. Commented Sep 18, 2018 at 17:00
  • 1
    @Input('step') step; is the correct one, also correct the selector, should be: selector: 'appRadialMenu' and to use it: <appRadialMenu [step]="4"></appRadialMenu>, and accessing the step in the constructor is wrong, use ngOnInit instead, or ngAfterViewInit Commented Sep 18, 2018 at 17:04
  • Do not answer your question in the question. Feel free to write an answer yourself -- you can even accept it. Commented Sep 18, 2018 at 20:29

2 Answers 2

1

You should create an alias for the input property so that you don't have to use another property named steps on the Directive.

Apart from that, you will get the changed steps count in your ngOnChanges. So use that instead of ngOnInit.

This should be your directive.

import { Directive, ElementRef, Input, OnChanges } from '@angular/core';

@Directive({
  selector: '[appRadialMenu]'
})
export class RadialMenuDirective implements OnChanges {
  @Input('appRadialMenu') step;

  constructor(private elRef: ElementRef) {
  }

  ngOnChanges() {
      console.log('Got steps as: ', this.step);
  }

}

Since you'll be using the appRadialMenu directive with an attribute binding syntax, it should be assigned a property that will be defined on your Component class.

Here's how you can use it in your Component Template:

<div [appRadialMenu]="steps"></div>

Here's a Sample StackBlitz for your reference.

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

Comments

0

You can pass values to directive in multiple ways using @Input() i.e.

  1. You can directly pass some value to directive i.e. [MyDirective]="someValue"
  2. You can create another input variable in directive to accept another value i.e. @Input('otherValue') otherValue: number

Html

<div [MyDirective]="someValue" [otherValue]="20">
     {{someValue | number: '1.0-0'}}
</div>

Directive

@Directive({
  selector: '[MyDirective]'
})
export class MyDirective implements OnChanges {

  @Input('MyDirective') value: number
  @Input('otherValue') otherValue: number
  constructor(private elRef: ElementRef) { }

  ngOnChanges() {
    console.log(this.value)
    console.log(this.otherValue)
  }
}

Note: You can pass any number of variables to directive using @Input().

Comments

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.