How can I change the value of an Angular template variable?

Issue

I want to change the value of a template variable based on a condition.

<ng-container *ngIf="'first' as myVar">
  <ng-container *ngIf="myVar == 'first'">
    <ng-container *ngIf="'later' as myVar">
      <div>{{myVar}}</div>
    </ng-container>
  </ng-container>

  <div>{{myVar}}</div>
</ng-container>

However I am getting

later
first

instead of

later
later

(probably the second variable is different than the first one and exists only in the scope of the second variable (which seems to be a weird way to implement template variables)).

Is there a simple way to change the value of a template variable?

I would also like to know if there is a way to join the condition ("myVar == 'first'") and the assignment ("'later' as myVar") into one expression instead of two nested <ng-container>.

Solution

Template Variables

For your main question, your elements can only see the the template variables of their parents.

For example, this will fail to compile:

<ng-container *ngIf="'later' as myVar">
  <div>{{myVar}}</div>
</ng-container>
<div>{{myVar}}</div> <!-- No parent TV or reference in component.ts -->

So your conclusion is right, in that it is a different value, although it isn’t all that weird if you think of it as living on that DOM-Element. They are more so meant as references to that particular element, and are indeed less useful for logic. For that you’re better off binding to your component.ts file.

In short, I don’t think reassigning of Template Variables is possible. You will just get the value of the closest parent.

Second Question

For your second question, this is a little shorter (but /w same result):

<ng-container *ngIf="'first' as myVar">
  <ng-container *ngIf="(myVar == 'first' ? 'later' : '') as myVar">
    <div>{{myVar}}</div>
  </ng-container>
  <div>{{myVar}}</div>
</ng-container>

You could also (ab)use ngTemplateOutlet to achieve something similar:

<ng-template #s [ngTemplateOutlet]="s" let-a [ngTemplateOutletContext]="{ $implicit: 'first' }">
    {{a}}
    <ng-template #t [ngTemplateOutlet]="t" let-b [ngTemplateOutletContext]="{ $implicit: a == 'first' ? 'later' : '' }">
    {{b}}
    </ng-template>
</ng-template>

Here’s a Stackblitz for you.

Presentation Logic in Component.ts

It is actually perfectly fine to have logic for presentation in your component. In fact it is pretty much the only thing that should be in your presentation components.

It is a best practice to use the approach of Container & Presentation Components.

Container component

  • Manages the state by interacting with service/store
  • Contains only minor presentation, like for example a header/title
  • Passes state to presentation components using input properties

Presentation component

  • Presents/renders the data, but does not directly interact with state
  • Communicates with container component using output properties

Answered By – H3AR7B3A7

Answer Checked By – Mildred Charles (AngularFixing Admin)

Leave a Reply

Your email address will not be published.