File

libs/upp-wdgt/src/components/upp-image/upp-image.ts

Description

The UppImageComponent is a versatile image component with cropping capabilities, lazy loading, and base64 image transformation. It is compatible with Angular's reactive forms as a ControlValueAccessor.

This component supports both readonly and editable modes. It uses a modal-based cropping interface (UppModalCropComponent) to allow users to crop images before upload.

Example :
```html
<upp-image
    [readonly]="false"
    [src]="imageSource"
    [crheight]="200"
    [crwidth]="200"
    (Changed)="onImageChange($event)">
</upp-image>
Example :

Extends

languageSupport

Implements

ControlValueAccessor OnInit OnChanges OnDestroy

Metadata

Index

Properties
Methods
Inputs
Outputs
Accessors

Constructor

constructor(lang: languageService, change: ChangeDetectorRef, controlContainer: ControlContainer, http: httpService, preload: preloadService, sanitizer: DomSanitizer, modalCtrl: ModalController)

Constructs the UppImageComponent and injects necessary dependencies.

  • If the component is used inside a reactive form, it will attempt to retrieve its associated FormControl from the FormGroup.
  • Implements ControlValueAccessor to allow two-way binding with Angular forms.
  • Supports image preprocessing, caching, and transformations (e.g., EXIF orientation adjustments).
Parameters :
Name Type Optional Description
lang languageService No

Language service for multi-language support.

change ChangeDetectorRef No

Change detector for triggering view updates.

controlContainer ControlContainer No

Provides access to the form control's parent FormGroup, enabling integration with reactive forms.

http httpService No

HTTP service for tracking online status and connectivity.

preload preloadService No

Preload service for caching and optimizing image loading.

sanitizer DomSanitizer No

Sanitizer for handling and securing image URLs.

modalCtrl ModalController No

Controller for managing modal interactions, such as cropping images.

Inputs

crheight
Type : string
Default value : '0'

The height constraint for cropping.

crwidth
Type : string
Default value : '0'

The width constraint for cropping.

formControlName
Type : string
Default value : ''

The name of the form control this input is bound to.

readonly
Type : boolean
Default value : true

Determines if the component is in readonly mode.

src
Type : string | null
Default value : null

The source of the image. Can be a URL or a base64 string.

value
Type : string | null

/

Outputs

Changed
Type : EventEmitter

Emits an event when the image is changed.

Methods

fileDelete
fileDelete()

Clears this image source

Returns : void
ngOnChanges
ngOnChanges()

Handles changes to the input properties, such as the image source.

Returns : void
ngOnDestroy
ngOnDestroy()

Cleans up subscriptions and resources when the component is destroyed.

Returns : void
ngOnInit
ngOnInit()

Initializes the component and subscribes to the online status.

Returns : void
OnChange
OnChange(event: Event)

Emits the Changed event when an image is modified.

Parameters :
Name Type Optional Description
event Event No

The change event from the file input.

Returns : any
OnLoaded
OnLoaded()

Updates the _loaded state when the image finishes loading. Triggers change detection to update the view.

Returns : void
registerOnChange
registerOnChange(fn: any)

Registers a callback for when the value changes.

Parameters :
Name Type Optional
fn any No
Returns : void
registerOnTouched
registerOnTouched(fn: any)

Registers a callback for when the control is touched.

Parameters :
Name Type Optional
fn any No
Returns : void
writeValue
writeValue(value: string | null)

Implements ControlValueAccessor to handle form binding.

Parameters :
Name Type Optional
value string | null No
Returns : void

Properties

_image
Type : ElementRef | null
Default value : null
Decorators :
@ViewChild('image', {static: false})

Image element reference in the template.

Public _loaded
Default value : false

Tracks whether the image has fully loaded.

Public _loading
Type : string
Default value : 'lazy'

Tracks the image loading mode (lazy or eager).

Public _online
Default value : true

Tracks the online status of the application.

Public formControl
Type : AbstractControl | null
Default value : null
Public formGroup
Type : FormGroup | null
Default value : null

optional FromGroup

Accessors

_cors
get_cors()

Determines if the image source requires the crossorigin attribute for server images.

The _cors getter checks if the src is an HTTP URL that is external to the base URL. This is used to handle cross-origin requests for server-hosted images.

Returns : boolean
_source
get_source()

Gets the current source of the image, which may be the base64 value, a cached value, or the original source URL.

Returns : SafeUrl | string | null
Base64
getBase64()

Retrieves the base64-encoded string of the image.

The Base64 getter uses a Promise to asynchronously generate a base64-encoded string from the image source. If the image is already processed, it returns the cached value (c64).

IsCached
getIsCached()

Checks whether the current image source is cached.

Returns : boolean
IsVisible
getIsVisible()

Determines whether the image is visible. Combines the _loaded state and whether the image is cached.

Online
setOnline(value: boolean)

Sets the online status and manages the online subscription.

Parameters :
Name Type Optional Description
value boolean No

The new online status (true for online, false for offline).

Returns : void
value
getvalue()

/

Returns : string | null
setvalue(v: string | null)

Sets a new value for the image.

The value accessor updates the internal _value and src properties when the provided value differs from the current src. It also triggers change detection, invokes the registered ControlValueAccessor callbacks, and emits the Changed event.

Parameters :
Name Type Optional Description
v string | null No

The new value for the image. This can be a base64 string or a URL.

Returns : void
<div class="background" [ngClass]="{ 'visible': !IsVisible, 'noevents': 'readonly' }">
    <ng-container *ngIf="src && (_loaded || _online || IsCached)">
        <img *ngIf="_cors === true" #image alt="unpispas image" [hidden]="!IsVisible" (load)="OnLoaded()" [src]="_source" [attr.loading]="_loading" crossorigin="anonymous" />
        <img *ngIf="_cors !== true" #image alt="unpispas image" [hidden]="!IsVisible" (load)="OnLoaded()" [src]="_source" [attr.loading]="_loading" />
    </ng-container>
    <ng-container *ngIf="src === null">
        <div class="nophoto"></div>
    </ng-container>
</div>
<div uppDataid="image-fileupload-button" *ngIf="!readonly" class="image-label" >
    <input #fileUploader uppDataid="image-fileupload-file" type="file" accept="image/*" style="display:none" (change)="OnChange($event)">
    <div class="actions">
        <ion-label tabindex="0" (click)="fileUploader.click()" (keydown.enter)="fileUploader.click()" (keydown.space)="fileUploader.click()">
            <ion-icon name="camera"></ion-icon>
            <br/>{{tr('@title_modify_image')}}
        </ion-label>
        <ion-label *ngIf="value !== null" tabindex="1" (click)="fileDelete()" (keydown.enter)="fileDelete()" (keydown.space)="fileDelete()">
            <ion-icon name="close-circle"></ion-icon>
            <br/>{{tr('@title_delete_image')}}
        </ion-label>    
    </div>
</div>

./upp-image.scss

:host {
    max-height: inherit;
    height: inherit;
    width: inherit;
    overflow: hidden;
    
    .noevents {
        pointer-events: none;
    }

    .image-label {
        position: absolute;
        display: block;
        top: 0px;
        left: 0px;
        height: 100%;
        width: 100%;
        background: rgba(var(--ion-background-color-rgb), 0.6);

        .actions {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 20px;
            height: 100%;
            width: 100%;

            ion-icon {
                font-size: 35px;
            }

            ion-label {
                display: flex;
                flex-direction: column;
                align-items: center;
                height: 65px;
                line-height: 8px;
                text-align: center;
                cursor: pointer;
            }    
        }
    }
    
    .background {
        margin: auto;
        
        height: inherit;
        width: 100%;
        object-fit: inherit;
        opacity: inherit;

        background-color: transparent;
        background-image: none;
        
        &.visible {
            background-attachment: local;
            background-size: cover;
            background-image: url('../../../assets/image/beer-loading.gif');
            background-repeat: no-repeat;
            background-position: center;
        }

        .nophoto {
            height: 100%;
            width: 100%;

            background-attachment: local;
            background-size: cover;
            background-image: url('../../../assets/image/no-photo.jpg');
            background-repeat: no-repeat;
            background-position: center;
        }
    }
    
    img {
        padding: var(--ui-image-padding, 0);
        
        display: block;
        height: 100%;
        width: 100%;
        max-height: inherit;
        object-fit: inherit;

        &[hidden] {
            visibility: hidden !important;
            display: block !important; 
        }  
    }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""