1

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>
ivan.vliza
  • 153
  • 3
  • 14
  • Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – ConnorsFan Sep 18 '18 at 16:58
  • 1
    Use an arrow function as the callback: `.click(() => { ... })`. More importantly, avoid using jQuery for event binding. – ConnorsFan Sep 18 '18 at 17:00
  • 1
    `@Input('step') step;` is the correct one, also correct the selector, should be: `selector: 'appRadialMenu'` and to use it: ``, and accessing the `step` in the constructor is wrong, use `ngOnInit` instead, or `ngAfterViewInit` – Hussein Sep 18 '18 at 17:04
  • Do not answer your question in the question. Feel free to write an answer yourself -- you can even accept it. – Lazar Ljubenović Sep 18 '18 at 20:29

2 Answers2

0

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.

SiddAjmera
  • 38,129
  • 5
  • 72
  • 110
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().

WasiF
  • 26,101
  • 16
  • 120
  • 128