Search code examples
angulartypescriptionic4

Show ion-button when *ngIf does not exist


I have an array of cards that displays download buttons. I wish to hide the download button in the first div if I have already downloaded and saved the data to the database and the second div then displays.

<ion-card *ngFor="let data of itemList.list let i = index">
  <ion-card-content>

    <div> <!-- I want this to display if *ngIf="n == data.task does not display -->
      <ion-button (click)="saveData(data.link)" >Download for offline use</ion-button>
    </div>

    <div *ngFor="let n of loop"> <!-- loops through keys in database -->
      <div *ngIf="n == data.task"> <!-- if data.task key exists the buttons display -->
        <div class = "linkButtons">
          <ion-button (click)="openForm(data.Type, data.task)">&nbsp;&nbsp;Open&nbsp;&nbsp;</ion-button>
          <ion-button (click)="syncData()">Sync</ion-button>
          <ion-button (click)="deleteAudit( n )">Delete</ion-button>
        </div>
      </div>
    </div>

  </ion-card-content>
</ion-card>   

Solution

  • You can't accomplish what you're trying to do with the template only, you can learn more about why here.

    What you can do is cache the results in your component with a Map.

    dataTasks = new Map<any, boolean>()
    taskEquals(data: any, n: any) {
        if (!this.dataTasks.get(data)) {
            this.dataTasks.set(data, data.task == n)
        }
        return data.task == n
    }
    
    hasTask(data: any) {
        return !!this.dataTasks.get(data)
    }
    

    Then your template code can use these functions:

    <ion-card *ngFor="let data of itemList.list let i = index">
      <ion-card-content>
    
        <div *ngIf="hasTask(data) == false">
          <ion-button (click)="saveData(data.link)">Download for offline use</ion-button>
        </div>
    
        <div *ngFor="let n of loop">
          <div *ngIf="taskEquals(data, n)">
            <div class = "linkButtons">
              <ion-button (click)="openForm(data.Type, data.task)">&nbsp;&nbsp;Open&nbsp;&nbsp;</ion-button>
              <ion-button (click)="syncData()">Sync</ion-button>
              <ion-button (click)="deleteAudit( n )">Delete</ion-button>
            </div>
          </div>
        </div>
    
      </ion-card-content>
    </ion-card>  
    

    An alternative solution without using Map would be to assign the result to a property on the data object.