4

I have two selectors dirA and dirNotA for my directive. The directive should proceed further based on the selector used. Is there any way to determine which selector was used within the directive?

I do not wish to have multiple directives nor a directive with parameters. I wish to have one directive with multiple selectors and to determine the course of action based on the selector used in the template.

Something like this

@Directive({
  selector: '[dirA], [dirNotA]`
})
class DirectiveA implement OnInit {
  ngOnInit() {
    // here we detected which selector was used
    if (dirASelector) {
      ...
    }

  }
}

Any ideas how can get this information in the directive itself?

ruth
  • 29,535
  • 4
  • 30
  • 57
s-f
  • 2,091
  • 22
  • 28
  • Please see if my answer [here](https://stackoverflow.com/a/60385060/6513921) is relevant for you. – ruth Feb 25 '20 at 09:04
  • Hi, not exactly. I'm absolutely fine to statically attach directive for elements in the code, but instead of doing `dirA="false"` I would like to have more clear `dirNotA`, because it only possible value for this directive and `dirA=12` doesn't make practical sense. – s-f Feb 25 '20 at 09:10
  • Please see if my answer is relevant for you. – ruth Feb 25 '20 at 09:34

4 Answers4

2

You can use inheritance.

class DirectiveAOrNotA implements OnInit {
// common logic here
}

@Directive({
  selector: '[dirA]`
})
export class DirectiveA extends DirectiveAOrNotA {
// differences here
}

@Directive({
  selector: '[dirNotA]`
})
export class DirectiveNotA extends DirectiveAOrNotA {
// differences here
}

mbojko
  • 13,503
  • 1
  • 16
  • 26
1

if you want just one directive you could use setters for inputs named after all the selectors and in their bodies set some private prop accordingly

probably a weird example but imagine something like this

@Directive({
  selector: "[addQA],[addTestId]",
})
export class AddQADirective implements OnInit, OnChanges {
  private value: string = "";

  @Input() public customName: string = "";

  @Input() public set addQA(value: string) {
    this.customName = "qa";
    this.value = value;
  }

  @Input() public set addTestId(value: string) {
    this.customName = "test";
    this.value = value;
  }

  constructor(private element: ElementRef<HTMLElement>) {}

  public ngOnInit(): void {
    if (!this.value) {
      return;
    }
    const attrName = `data-${this.customName}`;
    this.element.nativeElement.setAttribute(attrName, this.value);
  }
}
mizuki nakeshu
  • 1,315
  • 2
  • 9
  • 12
  • how would both be called when you use just one of the variants? but yes, you need to set value for the setter to be called and I overlooked the valueless requirement in OP – mizuki nakeshu Aug 11 '22 at 08:39
  • no they don't, only the one matching directive selector you used (actually none of them if you use the square bracket form without value, if you use it without square brackets it gets called with undefined - which then even does what OP wants) – mizuki nakeshu Aug 12 '22 at 10:23
0

See answer https://stackoverflow.com/a/52964860 by Christian Vincenzo Traina (Oct 24, 2018)

Yes, you can. Just define a `@Input` property for every selector of your directive
...

The answer includes example code & further explanation.

-1

You could use ElementRef and check for the selector in it's attributes.

Directive

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

@Directive({
  selector: '[dirA], [dirNotA]'
})
class DirectiveA implement OnInit {
  constructor(private _elRef: ElementRef) { }

  ngOnInit() {
    if ((this._elRef.nativeElement.attributes).hasOwnProperty('dirA')) {
      // selector is 'dirA'
    } else if ((this._elRef.nativeElement.attributes).hasOwnProperty('dirNotA')) {
      // selector is 'dirNotA'
    }
  }
}

Working example: Stackblitz

ruth
  • 29,535
  • 4
  • 30
  • 57
  • 1
    unfortunatley, it doesn't work for me. `attributes`property is empty. for my real-life scenario from which I made a question this will not work in princiapl. I want to use `dirA` as structural directive, i.e. `*dirA` and it doesn't have element attached to it – s-f Feb 25 '20 at 14:59