Skip to main content

upp-image

A versatile image component with built-in cropping, lazy loading, EXIF orientation handling, and base64 conversion. It integrates with Angular reactive forms as a ControlValueAccessor, supporting readonly display plus two editable interaction modes: direct upload (upload) and inline configuration (config).

When to Use

  • You need to display an image that may come from a URL or a base64 string.
  • You want the previous direct-upload flow in editable mode (mode="upload", default).
  • You want users to configure image content (local upload, avatar, or internet search) from an inline settings panel (mode="config").
  • You need an image input that works inside Angular reactive forms.
  • You need automatic EXIF orientation correction for user-uploaded photos.
  • You want lazy loading and preload/cache integration for server-hosted images.

Demo

Source Code

<div class="demo-scroll-container">
<upp-scrollable [scrollbar]="'y'">
<div class="demo-content">
<h2>upp-image</h2>
<p class="demo-description">Product photo display &amp; editing. In <strong>upload</strong> mode it opens the file picker directly; in <strong>config</strong> mode it opens avatar/upload/search options plus crop on the current image when available.</p>

<!-- Controls -->
<div class="demo-controls">
<ion-button size="small" (click)="toggleReadonly()">
<ion-icon name="lock-closed-outline" slot="start" *ngIf="isReadonly"></ion-icon>
<ion-icon name="lock-open-outline" slot="start" *ngIf="!isReadonly"></ion-icon>
Editable: {{ !isReadonly }}
</ion-button>

<div class="demo-control-group">
<label class="demo-label">Mode</label>
<div class="demo-mode-buttons">
<ion-button size="small" [fill]="selectedMode === 'upload' ? 'solid' : 'outline'" (click)="setMode('upload')">upload</ion-button>
<ion-button size="small" [fill]="selectedMode === 'config' ? 'solid' : 'outline'" (click)="setMode('config')">config</ion-button>
</div>
</div>

<div class="demo-control-group">
<label class="demo-label">Search seed</label>
<input type="text" [(ngModel)]="searchText" class="demo-text-input" maxlength="16">
</div>

<div class="demo-control-group">
<label class="demo-label">Crop width</label>
<input type="number" [(ngModel)]="crwidth" class="demo-number-input">
</div>

<div class="demo-control-group">
<label class="demo-label">Crop height</label>
<input type="number" [(ngModel)]="crheight" class="demo-number-input">
</div>
</div>

<!-- Updated banner -->
<div class="demo-toast" *ngIf="imageUpdated">
<ion-icon name="checkmark-circle-outline"></ion-icon>
Image updated!
</div>

<!-- Single image: toggles readonly/editable -->
<div class="demo-section">
<h3>Product Photo ({{ isReadonly ? 'readonly' : 'editable' }}, mode: {{ selectedMode }})</h3>
<p class="demo-label">
{{ isReadonly ? 'Click the lock to enable editing.' : (selectedMode === 'config'
? 'Use settings for avatar, upload, search, or crop the current image.'
: 'Use camera icon to upload a local image directly.') }}
</p>
<div class="image-frame">
<upp-image #imageRef
[src]="imageSrc"
[readonly]="isReadonly"
[mode]="selectedMode"
[search]="searchText"
[crwidth]="crwidth"
[crheight]="crheight"
(Changed)="onImageChanged(imageRef)">
</upp-image>
</div>
</div>
</div>
</upp-scrollable>
</div>

API Reference

upp-image

Selector: upp-image

Implements: ControlValueAccessor, OnInit, OnChanges, OnDestroy

Inputs

NameTypeDefaultDescription
readonlybooleantrueWhen true, the image is display-only. When false, the image action icon is enabled.
mode'upload' | 'config''upload'Editable interaction mode. upload opens the OS file picker directly (legacy behavior). config opens the inline settings panel.
searchstring | nullnullSeed text copied into the config panel. Used by avatar generation and internet image search when opening mode="config".
srcstring | nullnullImage source. Can be a URL or a base64 string.
crheightstring'0'Crop height constraint in pixels (passed to the crop modal).
crwidthstring'0'Crop width constraint in pixels (passed to the crop modal).
formControlNamestring''Name of the reactive form control this component is bound to.
valuestring | null(derived)The current image value (base64 or URL). Supports two-way binding via ControlValueAccessor.

Configuration Mode Options

When mode="config" and the widget is editable:

  • Avatar (/photo/avatar): builds an avatar URL from text + configurable hex colors.
  • Color selection UI: uses the reusable upp-color widget for background/text color selection.
  • Upload: opens local file picker, then crop modal.
  • Search (/photo/search): requests an internet product image and enables Use Found Image only when a valid result is returned.

Both backend routes are exposed under the server /photo group.

Outputs

NameTypeDescription
ChangedEventEmitter<any>Emits whenever the image is modified (file selected, cropped, or cleared).

Computed Properties

PropertyTypeDescription
IsCachedbooleanWhether the current src is available in the preload cache.
IsVisiblebooleantrue if the image has loaded or is cached.
Base64Promise<string | null>Asynchronously returns the base64-encoded PNG representation of the current image.

upp-modal-crop-image

Selector: upp-modal-crop-image

Internal modal component used by upp-image for cropping. Not intended for direct use.

NameTypeDescription
@Input() imageanyThe image element to crop.
@Input() heightnumberDesired crop height.
@Input() widthnumberDesired crop width.