1
votes

I'm trying to create a Angular structural directive that will be available only to a specific HTML element (div).

However, when I try to set the structural directive selector to div[nameOfDirective], an error occurs: "Can't bind to 'nameOfDirective' since it isn't a known property of 'div'.".

It works perfectly if the selector is only the attribute [nameOfDirective].

I've created a plunker simulating the error: https://plnkr.co/edit/C1c93HUpi1vWk9dP
The plunker will not preview, since the compilation error occurs. Open console to see it.
If you change the directive selector in file restricted-element.directive.ts, it will preview normally.

Am I doing something wrong or is it a bug?

1

1 Answers

0
votes

The error is in the html in this case the directive must be declared like this:

<div [red]="'fasf'" [redData]="'0909'">
    Restricted Element Directive
</div>

You can read see more about this in https://angular.io/guide/attribute-directives#binding-to-an-input-property

I edit to explain how the directive should be used correctly

After reading exhaustively in the angular documentation how it works and what it is a directive, I could see that what you are trying to do is an error, given that if you use the syntax of * you are telling Angular that you are declaring a structural directive, which reason why Angular will always turn your element into what I show below:

Here we make use of the structural directive ngIf:

<div *ngIf="hero" class="name">{{hero.name}}</div>

And Angular will always translate the attribute into an element, wrapped around the host element, like this. *ngIf

<ng-template [ngIf]="hero">
  <div class="name">{{hero.name}}</div>
</ng-template>

And while nowhere in the angular documentation does it say that you can't use a selector from a structural directive for a specific DOM element, it also says absolutely nothing that you can use it.

But if you say that a structural directive does the following transformation:

  • The *ngIf directive moved to the element where it became a property binding,[ngIf].
  • The rest of the , including its class attribute, moved inside the element.

And this is where the error shown by the console occurs, since your selector indicates that the network directive can only be inside a div and Angular has manipulated the directive and has put it inside an ng-template.

When this is declared:

@Directive({
  selector: 'div[red]'
})

Directive is restricted only to the div and if in the html you tell Angular to use it as a structured directive:

<div *red="'fasf'; data '0909'">
  Restricted Element Directive
</div>

Internally, Angular translates in this:

<ng-template red [red]="'fasf'" [redData]="'0909'">
  <div>Restricted Element Directive</div>
</ng-template>

Which causes the error because your directive was restricted for the div element. The documentation explains this much more summarized and explicit here https://angular.io/guide/structural-directives#the-asterisk--prefix

So, so that your code does not cause an error:

  • You should use an attribute directive
  • Or remove the div restriction.