Skip to main content

upp-visible-control

A wrapper component that uses the VisibleDirective to detect when its content enters or leaves the viewport. It automatically detaches Angular change detection while the component is hidden and reattaches it when visible, providing a significant performance optimization for lists with many items.

When to Use

  • You have a scrollable container with many items and want to avoid unnecessary change detection cycles for off-screen elements.
  • You need to track which items are currently visible in a scroll container (e.g., analytics, lazy rendering, virtual scroll alternatives).
  • You want to optimize rendering performance by pausing updates on hidden content.

Demo

Source Code

<h2>upp-visible-control</h2>
<p class="demo-description">Lazy image gallery — content renders only when <code>upp-visible-control</code> detects the item is in the viewport.</p>

<div class="demo-controls">
<ion-badge color="primary" class="counter-badge">
{{ visibleCount }} of {{ images.length }} images in viewport
</ion-badge>
<span class="hint">Scroll down to load more</span>
</div>

<div class="demo-section">
<div class="gallery-scroll">
<div *ngFor="let img of images; let i = index" class="gallery-slot">
<upp-visible-control (visibilityChange)="onVisibilityChange(i, $event)">
<div class="image-card" *ngIf="visibilityMap[i]; else placeholder">
<div class="image-preview" [style.background]="img.color">
<ion-icon [name]="img.icon" class="image-icon"></ion-icon>
</div>
<div class="image-info">
<span class="image-title">{{ img.title }}</span>
<span class="image-desc">{{ img.description }}</span>
</div>
</div>
<ng-template #placeholder>
<div class="image-card image-card--placeholder">
<div class="image-preview image-preview--placeholder">
<ion-icon name="image-outline" class="image-icon image-icon--placeholder"></ion-icon>
</div>
<div class="image-info">
<span class="placeholder-bar placeholder-bar--title"></span>
<span class="placeholder-bar placeholder-bar--desc"></span>
</div>
</div>
</ng-template>
</upp-visible-control>
</div>
</div>
</div>

API Reference

upp-visible-control

Selector: upp-visible-control

TypeNameDescription
@Input()mode: 'content' | 'fill'Layout participation of the wrapper. Defaults to content (neutral: the projected content sizes to itself). Set to fill to make the host and its internal observed <span> a vertical flex chain that stretches to fill the parent, so the wrapped content can occupy the full available height without the consumer penetrating the widget's internals.
@Output()visibilityChange: EventEmitter<boolean>Emits true when the component enters the viewport and false when it leaves.

Behavior:

  • On initialization (ngAfterViewInit), if the component is not visible, change detection is detached immediately.
  • When the component becomes hidden, change detection is detached to save rendering cycles.
  • When the component becomes visible again, change detection is reattached and detectChanges() is called to refresh the view.
  • With mode="fill", the widget owns the full-height layout (--fill host class); consumers should not use ::ng-deep to reach the inner <span>.