I have a class section on a DIV to be rendered. It works as expected.
<div *ngIf="decoded; then coordinates"></div>
<ng-template #coordinates>
<div >...</div>
</ng-template>
I tried moving the class assignment to the DIV containing the directive. The rendition did not work, though.
<div *ngIf="decoded; then coordinates" ></div>
<ng-template #coordinates>
<div>...</div>
</ng-template>
The outer DIV vanishes as a whole, being replaced by the contents of the template. It bugs me because I'm forced to add an extra DIV around everything in my template if I have several components in it. (Also, it seems kind of weird to me that we don't retain any properties of the tag used with *ngIf
and can use any arbitrary one, while it seems to work for *ngFor
.)
<div *ngIf="decoded; then coordinates"></div>
<ng-template #coordinates>
<div >
<div>...</div>
<span>...</span>
<bzz>...</bzz>
</div>
</ng-template>
I tried cheating the browser by setting the class on template but since it's not actually rendered in the DOM as such, it failed, of course.
<div *ngIf="decoded; then coordinates"></div>
<ng-template #coordinates >
<div...</div>
</ng-template>
is there a way to force the DIV with the conditional directive to retain its class when being rendered according to the template's contents?
CodePudding user response:
You can try to use ng-container
and apply *ngIf
to it, in this case it should work as you expected
<div >
<ng-container *ngIf="decoded; then coordinates"></ng-container>
</div>
<ng-template #coordinates>
<div>...</div>
</ng-template>
CodePudding user response:
TL;DR: Angular is doing what you asked it to; you used then
to tell it to render something other than the element the directive was on in the truth-y case. If that's not the behaviour you want, don't do that.
Structural directives like *ngIf
and *ngFor
are really a shorthand that gets expanded (this used to be referred to as "desugaring"), look at the examples in https://angular.io/guide/structural-directives or more specifically https://angular.io/api/common/NgIf#description:
Simple form with shorthand syntax:
<div *ngIf="condition">Content to render when condition is true.</div>
Simple form with expanded syntax:
<ng-template [ngIf]="condition"> <div>Content to render when condition is true.</div> </ng-template>
Note that everything gets wrapped up in ng-template
s for conditional rendering.
If you had written your template like this:
<div *ngIf="decoded" >...</div>
it would get expanded to:
<ng-template [ngIf]="decoded">
<div >...</div>
</ng-template>
and what would actually be rendered is:
<div >...</div>
Note that the class is still included, consistent with what you've experienced in other structural directives.
However, when you use then
, the shorthand:
<div *ngIf="decoded; then coordinates" ></div>
<ng-template #coordinates>
<div>...</div>
</ng-template>
is expanded to:
<ng-template [ngIf]="decoded" [ngIfThen]="coordinates">
<div ></div>
</ng-template>
<ng-template #coordinates>
<div>...</div>
</ng-template>
The content of the first ng-template
is now irrelevant, because that's not what's rendered in either case. It's either going to render the #coordinates
template content or nothing, so you get:
<div>...</div>
and your class seems to have disappeared. But that's what you asked for; the point of then
is to not render the element the *ngIf
was on, in the truth-y case, but to render something else instead.
For more on these underlying ng-
elements, I wrote Angular's "ng-" elements on my blog.
CodePudding user response:
I suggest to take a look on this great article Everything you need to know about ng-template, ng-content, ng-container, and *ngTemplateOutlet in Angula
It contains all you need to know about Angular's structural directives with a good explanation and examples.