简体   繁体   English

Angular - 获取指令的选择器名称

[英]Angular - Get the selector name of the directive

I created a directive with multiple selectors, so I can access the same directive with different selectors.我创建了一个带有多个选择器的指令,所以我可以使用不同的选择器访问同一个指令。 What I'm trying to achieve is to get the selector name that called the directive in my directive.我想要实现的是获取在我的指令中调用该指令的选择器名称

The following code will explain this even better:下面的代码将更好地解释这一点:

So this is my multi-selector directive:所以这是我的多选择器指令:

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

const inputs = [
  'someSelector.A', 'someSelector.B'
];

const selector = `
  [someSelector.A], [someSelector.B]
`;

@Directive({ selector, inputs })
export class MyDirective implements OnInit {

  constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) { }

  ngOnInit() {
    // I need to know here what is the current selector:
    // Is it: "someSelector.A" or "someSelector.B"?
  }
}

And this is how I would like to call the directive in the HTML:这就是我想调用 HTML 中的指令的方式:

<element *someSelector.A></element>

<!-- Or: -->

<element *someSelector.B></element>

Okay, so the way that flex is doing it, is that they are passing the inputs to the decorator, then the variables are generated on the directive.好吧,flex 的做法是将输入传递给装饰器,然后在指令上生成变量。 If the directive is not passed to the html element it is undefined on the directive inputs.如果指令未传递给 html 元素,则它在指令输入中未定义。 It looks like this:它看起来像这样:

export interface DirectiveAB {
  'someSelector.A': string;
  'someSelector.B': number;
}
type Selectors =  'someSelector.A' | 'someSelector.B';

const inputs = ['someSelector.A', 'someSelector.B'];

@Directive({ selector: '[someSelector.A], [someSelector.B]', inputs })
export class DirectiveAB implements OnInit {

  ngOnInit() {
    console.log(this.hasSelector('someSelector.A'));
    console.log(this.hasSelector('someSelector.B'));
  }

  hasSelector(selector: Selectors) {
    return typeof this[selector] !== 'undefined'
  }
}
<!-- prints true for "A"; false for "B" -->
<div someSelector.A></div>

<!-- prints false for "A"; true for "B" -->
<div someSelector.B></div>

You could separate the directives into two and extend a root directive.您可以将指令分成两部分并扩展根指令。 This is really how directives should be used if you want to have different functionality for a different selector.如果您想为不同的选择器提供不同的功能,这就是指令的实际使用方式。

import { Directive } from '@angular/core';

@Directive({ selector: '*' })
export class DirectiveRoot implements OnInit {
  ngOnInit() {
    console.log(this);
    if (this instanceof DirectiveA) {
      console.log('Directive A!');
    }
  }
}

@Directive({ selector: '[someSelector.A]' })
export class DirectiveA extends DirectiveRoot {}

@Directive({ selector: '[someSelector.B]' })
export class DirectiveB extends DirectiveRoot {}
<!-- prints DirectiveA to the console -->
<div someSelector.A></div>

<!-- prints DirectiveB to the console -->
<div someSelector.B></div>

Another option is to look at the element itself and check to see if the attribute exists:另一种选择是查看元素本身并检查属性是否存在:

@Directive({ selector: '[someSelector.A], [someSelector.B]' })
export class DirectiveAB implements OnInit {
  constructor(private readonly ref: ViewContainerRef) {}

  ngOnInit() {
    console.log(this.ref.element.nativeElement.hasAttribute('someSelector.A'));
    console.log(this.ref.element.nativeElement.hasAttribute('someSelector.B'));
  }
}
<!-- prints true for "A"; false for "B" -->
<div someSelector.A></div>

<!-- prints false for "A"; true for "B" -->
<div someSelector.B></div>

not really sure what you're trying to accomplish, but you can just check the inputs that match the selector in a few different ways不太确定您要完成什么,但您可以通过几种不同的方式检查与选择器匹配的输入

@Directive({
  selector: '[myDirective.A], [myDirective.B]',
})
export class MyDirective {
  @Input('myDirective.A')
  inputA;

  @Input('myDirective.B')
  inputB;

  constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) { }

  ngOnInit() {
    if (this.inputA !== undefined) {
      // used directive A
    } else if (this.inputB !== undefined) {
      // used directive B
    }
  }
}

or your can check it in a setter:或者你可以在 setter 中检查它:

@Directive({
  selector: '[myDirective.A], [myDirective.B]',
})
export class MyDirective {
  @Input('myDirective.A')
  set inputA(valueA) {
    // will only run if A selector used
  }

  @Input('myDirective.B')
  set inputB(valueB) {
    // will only run if B selector used
  }

  constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) { }

}

in template:在模板中:

<div *myDirective.A></div>
<div *myDirective.B></div>

https://stackblitz.com/edit/angular-92yazy?file=src%2Fapp%2Fapp.component.html https://stackblitz.com/edit/angular-92yazy?file=src%2Fapp%2Fapp.component.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM