Virtual Scroll Change Size of Single Item


#1

I am working on implementing a VirtualScroll list. My current implementation is:

<ion-list #virtualScroll [virtualScroll]="items" approxItemHeight="52px" >

    <div *virtualItem="let item">

      <button ion-button (click)="handleClick(item)" [style.height]="item.isSelected ? '70px' : '52px'" >

        <ion-icon name="square" class="tile-icon"></ion-icon>

        <div class="label-container">

          <ion-label text-left>{{property.p1}}</ion-label>
          <ion-label text-left>{{property.p2}}</ion-label>

        </div>

        <ion-icon name="square" class="cellular-icon"></ion-icon>
        <ion-icon name="square" class="gateway-icon"></ion-icon>

      </button>

    </div>

  </ion-list>

With just this code, when I click on one of the items/buttons the size of that button changes, but none of the other items move, so it overlaps them. I can adjust the click handler to include the following:

handleClick( item ) {
   item.isSelected = !item.isSelected;
   this.virtualScroll.readUpdate(true);
   this.virtualScroll.renderVirtual(false);
   this.virtualScroll.resize();
}

It will adjust the locations of all of the other items, but it also recalculates the item list, and the item that was clicked (and the size was adjusted for) jumps to a new location.

Any suggestions of how to get the benefits of the virtual scroll, along with the ability to click and resize a single item in the list without having its location jump?


#2

Any ideas or thoughts on this??


#3

Hello, I had the same requirement and managed to realize it.
It seems the interface of ion-virtual-scroll has changed since you tried it, I’m on Ionic 4 RC.0 and didn’t find the methods you used.

However, I used the following method to just redraw the resized item when the user taps on it.
The item will be highlighted and expanded to show some details about it.

HTML:

<ion-virtual-scroll #ordersVirtualScroll [items]="ordersFiltered">
	<ion-item detail *virtualItem="let order" (click)="onItemTapped($event)">
		<ion-label class="order-item-label">
			{{ order.orderNr }}
		</ion-label>
		<ion-card *ngIf="order == selectedOrder" class="details-card-flat">
			<ion-card-content>
				<!-- showing some details here -->
			</ion-card-content>
		</ion-card>
	</ion-item>
</ion-virtual-scroll>  

TypeScript:

selectedOrder: Order;
selectedItem: IonItem;
@ViewChild("ordersVirtualScroll")
ordersVirtualScroll: IonVirtualScroll;

	onItemTapped(event) {
		this.onItemSelected(event.srcElement, event.srcElement.$ionCell.value)
	}

	onItemSelected(item: IonItem, order: Order) {
			// if there was already an item selected
			if(this.selectedItem) {
				// remove highlighting from previous selected item
				this.selectedItem.color = undefined;

				// if the tapped item was already selected -> deselect it
				if(order == this.selectedOrder) {
					this.selectedItem = undefined;
					this.selectedOrder = undefined;
					// collapse
					this.ordersVirtualScroll.checkRange(this.ordersFiltered.indexOf(order), 1);
					return;
				}
			}

			this.selectedItem = item; 
			if(this.selectedOrder) {
				// collapse previously selected item
				this.ordersVirtualScroll.checkRange(this.ordersFiltered.indexOf(this.selectedOrder), 1);
			}
			this.selectedOrder = order;
			// expand newly selected item
			this.ordersVirtualScroll.checkRange(this.ordersFiltered.indexOf(this.selectedOrder), 1);
			this.selectedItem.color = "primary";
		}