Referring elements in ion-item of ion-list in TypeScript


#1

I have a list of photo objects in a photos object. These photos are shown in ion-list. And for each item I have a like, comment, and share buttons.

I built the share button with ion-fab so i can open two share buttons (share on facebook, twitter) when the share button in the ion-card is clicked.

What I want to do is hide the like and comment buttons when the share ion-fab opens.

<ion-list>
    <ion-card *ngFor="let photo of photos | async; let i = index;">
        <img [src]="photo.img"/>
        <span>{{photo.caption}}</span>
        <button ion-button>like</button>
        <button ion-button>comment</button>
        <ion-fab right>
            <button ion-fab (click)="shareFabClicked(photo, i)">
                <ion-icon name="share-alt"></ion-icon>
            </button>
            <ion-fab-list side="left">
                <button ion-fab (click)="share(photo, 'facebook')">
                    <ion-icon name="logo-facebook"></ion-icon>
                </button>
                <button ion-fab (click)="share(photo, 'twitter')">
                    <ion-icon name="logo-twitter"></ion-icon>
                </button>
            </ion-fab-list>
        </ion-fab>
    </ion-card>
</ion-list>

Assume that there is sass to style each element in the ion-card.

I need help on hiding the like and comment buttons when the share ion-fab opens. In general, how do you refer elements in an ion-item (or ion-card) of an ion-list and manipulate each element without affecting elements of other ion-items

Note: One thing i can do (but chose not to do) is have flags in the photo object to hide and show each button. The reason I did not want to go with this approach is the photos object can be very big and I did not want to add more data to it.

Thank you!


#2

Directly or indirectly, this is really your only option, and I think doing it directly (putting this flag into the photo object) is the cleanest and most straightforward way to go.

By “indirectly”, you could theoretically create a separate parallel array containing only the flags and use the index to link them. I find this unwieldy, and you still have as many booleans as you do photos, so there isn’t really any gain in terms of memory usage.

This strikes me as premature optimization.


#3

Answering my question based on the answer from Akash I got in stack overflow:

Copy-pasting the solution I wrote on stack overflow:

The solution involves two TypeScript variables, ngClass, and one sass class. And there is also a reference to the share ion-fab.

In the HTML code, [ngClass]="{'hide' : hide && index==i} is added in the like and comment tags. And #shareFab is added in the ion-fab tag.

<ion-list>
    <ion-card *ngFor="let photo of photos | async; let i = index;">
        <img [src]="photo.img"/>
        <span>{{photo.caption}}</span>

        <!-- apply the 'hide' class if hide = true and index = i -->
        <button ion-button [ngClass]="{'hide' : hide && index==i}>
            like
        </button>

        <button ion-button [ngClass]="{'hide' : hide && index==i}>
            comment
        </button>

        <ion-fab right #shareFab>
            <button ion-fab (click)="shareFabClicked(photo, i, shareFab)">
                <ion-icon name="share-alt"></ion-icon>
            </button>
            <ion-fab-list side="left">
                <button ion-fab (click)="share(photo, 'facebook')">
                    <ion-icon name="logo-facebook"></ion-icon>
                </button>
                <button ion-fab (click)="share(photo, 'twitter')">
                    <ion-icon name="logo-twitter"></ion-icon>
                </button>
            </ion-fab-list>
        </ion-fab>
    </ion-card>
</ion-list>

And in the sass code, the hide class is defined:

.hide {
  visibility: hidden;
}

And finally, in the TypeScript code, in the share method, the hide and index variables are set to hide/show the like and comment buttons according to the state of the share fab button:

hide: Boolean; 
index: Number;

shareFabClicked(p, i, shareFab: FabContainer) { 
    console.log('share fab clicked');

    if (shareFab._listsActive) {
        console.log('fab closing');
        this.hide = false;
    } else {
        console.log('fab opening');
        this.hide = true;
    }
    this.index = i;

    // TODO: share functionality
}

So basically, if index is equal to the index of the selected row and hide is true, the like and comment of the same row will be hidden; otherwise those two buttons are visible.


#4

How can you ensure that only one set of buttons is to be hidden at any given time?


#5

That’s what the index is for. For example, when index is 0 (first row), the statement hide && index==i becomes false for all other rows; so buttons on rows other than row 0 will be visible.


#6

If you’re happy with that, great. I didn’t realize initially that you would be content with a solution that allowed only one set of buttons to be hidden.