JoeyD
JoeyD

Reputation: 743

Angular *ngIf Directive Does Not Trigger Change Detection When Bound to a Function

I have a button that I would like to show only if something is dirty and requires a save. I have the following within my HTML

<mat-action-row>
    <button mat-raised-button color="primary" *ngIf="IsDirty(segmentGroup)"
         (click)="Save(segmentGroup)">Save</button>
</mat-action-row>

Here is the IsDirty Method in the TS

IsDirty(segmentGroup: SegmentGroup) {
    // Segment Group Dirty
    if (segmentGroup.isDirty)
      return true;

    segmentGroup.segmentDefinitions.forEach(segmentDefinition => {
      if (segmentDefinition.isDirty || segmentDefinition.startTimeLineDefinition.isDirty || segmentDefinition.endTimeLineDefinition.isDirty)
        return true;
    });

    return false;
  }

I need to check 3 levels of the object for an is dirty field, ie itself, a child object that is within an array, and a child object of the child within the array.

The issue i have is, the *ngIf method is called when the button is rendered and only when the button is rendered. Its not bound to a property therefore change detection doesnt trigger anything. So if I update IsDirty on any of the 3 levels the button never shows.

Is there a way to force the re-render or execution of the ngIf when either a property is changed or on a (change) event on the input?

Upvotes: 0

Views: 2579

Answers (1)

Marshal
Marshal

Reputation: 11081

I believe you answered your own question, using a function for the *ngIf directive will only be evaluated when the element is connected to the DOM and subsequent change detection cycles triggered by other means.

You could programmatically force change detection per the comment above to force the function call however, I believe the more appropriate implementation is as you pointed out, to bind the directive to a local class variable.

  • Calling functions directly from template markup is frowned upon for performance reasons

isDirty = false

<button *ngIf="isDirty">

isDirty = true

The above will trigger change detection because false is no longer equal to true, hence the term "change detection".


*ngIf="isDirty()"

This will never trigger change detection without some other means because function is always equal to function and it never changes... thus no change to trigger "change detection"


Set a boolean value to a local variable and bind that to the *ngIf directive, then find some other means to trigger your isDirty function to set that boolean value... on form change or input change is the typical implementation to calling a function like this.

Upvotes: 2

Related Questions