src/app/features/file/edit-photo/edit-photo.component.ts

Extends

EditFileComponent

Implements

OnInit

Metadata

Relationships

Used by

No results matching.

Depends on

Index

Properties
Methods
Inputs
Outputs

Inputs

entity
Type : Entity
Inherited from EditFileComponent
formFieldConfig
Type : FormFieldConfig
Inherited from EditFileComponent
aria-describedby
Type : string
disabled
Type : boolean
ngControl
Type : any
Default value : inject(NgControl, { optional: true, self: true })
placeholder
Type : string
required
Type : boolean
value
Type : T

Outputs

valueChange
Type : EventEmitter

Methods

delete
delete()
Inherited from EditFileComponent
Returns : void
Protected deleteExistingFile
deleteExistingFile()
Inherited from EditFileComponent
Returns : void
Async onFileSelected
onFileSelected(file: File)
Inherited from EditFileComponent
Parameters :
Name Type Optional
file File No
Returns : Promise<void>
openPopup
openPopup()
Returns : void
Protected resetFile
resetFile()
Inherited from EditFileComponent
Returns : void
formClicked
formClicked()
Inherited from EditFileComponent
Returns : void
Protected saveNewFile
saveNewFile(file: File)
Inherited from EditFileComponent
Parameters :
Name Type Optional
file File No
Returns : void
Protected setInitialValue
setInitialValue()
Inherited from EditFileComponent

Template method to allow easy override of mapping the initialValue from the formControl.

Returns : void
showFile
showFile()
Inherited from EditFileComponent
Returns : void
blur
blur()
Returns : void
focus
focus()
Returns : void
onContainerClick
onContainerClick(event: MouseEvent)
Parameters :
Name Type Optional
event MouseEvent No
Returns : void
registerOnChange
registerOnChange(fn: any)
Parameters :
Name Type Optional
fn any No
Returns : void
registerOnTouched
registerOnTouched(fn: any)
Parameters :
Name Type Optional
fn any No
Returns : void
setDescribedByIds
setDescribedByIds(ids: string[])
Parameters :
Name Type Optional
ids string[] No
Returns : void
setDisabledState
setDisabledState(isDisabled: boolean)
Parameters :
Name Type Optional
isDisabled boolean No
Returns : void
writeValue
writeValue(value: T, notifyFormControl: unknown)

Implementation for Angular ControlValueAccessor interface that links the form control value to the component value

Parameters :
Name Type Optional Default value Description
value T No

The new value to set

notifyFormControl unknown No false

Whether to notify the FormControl of this change (for internal updates)

Returns : void

Properties

Readonly imgPath
Type : unknown
Default value : signal<SafeUrl>(this.defaultImage)
acceptedFileTypes
Type : string
Default value : "*"
Inherited from EditFileComponent

The accepted file types for file selection dialog. If not defined, allows any file.

Protected fileService
Type : unknown
Default value : inject(FileService)
Inherited from EditFileComponent
fileUploadInput
Type : ElementRef<HTMLInputElement>
Decorators :
@ViewChild('fileUpload')
Inherited from EditFileComponent
Readonly hasControlValue
Type : unknown
Default value : signal<boolean>(false)
Inherited from EditFileComponent
initialValue
Type : string
Inherited from EditFileComponent
Readonly isControlEnabled
Type : unknown
Default value : signal<boolean>(false)
Inherited from EditFileComponent
Protected navigator
Type : unknown
Default value : inject<Navigator>(NAVIGATOR_TOKEN)
Inherited from EditFileComponent
controlType
Type : string
Default value : "custom-control"
elementRef
Type : unknown
Default value : inject<ElementRef<HTMLElement>>(ElementRef)
Readonly enabled
Type : Signal<boolean>
Default value : computed(() => !this._disabled())

Whether the control is currently enabled, as a signal (tracks disabled).

errorStateMatcher
Type : unknown
Default value : inject(ErrorStateMatcher)
id
Type : unknown
Default value : `custom-form-control-${CustomFormControlDirective.nextId++}`
Static nextId
Type : number
Default value : 0
onChange
Type : unknown
Default value : () => {...}
onTouched
Type : unknown
Default value : () => {...}
parentForm
Type : unknown
Default value : inject(NgForm, { optional: true })
parentFormGroup
Type : unknown
Default value : inject(FormGroupDirective, { optional: true })
stateChanges
Type : unknown
Default value : new Subject<void>()
Readonly valueSignal
Type : Signal<T>
Default value : computed(() => this._value())

The current value of the control as a signal. Authoritative in both modes: it reflects the bound FormControl (synced in ngDoCheck) as well as [(value)] / writeValue updates.

import {
  ChangeDetectionStrategy,
  Component,
  inject,
  OnInit,
  signal,
} from "@angular/core";
import { MatButtonModule } from "@angular/material/button";
import { MatDialog } from "@angular/material/dialog";
import { MatTooltipModule } from "@angular/material/tooltip";
import { SafeUrl } from "@angular/platform-browser";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { DynamicComponent } from "../../../core/config/dynamic-components/dynamic-component.decorator";
import { EditFileComponent } from "../edit-file/edit-file.component";
import { resizeImage } from "../file-utils";
import { ImagePopupComponent } from "./image-popup/image-popup.component";

@DynamicComponent("EditPhoto")
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-edit-photo",
  templateUrl: "./edit-photo.component.html",
  styleUrls: ["./edit-photo.component.scss"],
  imports: [MatButtonModule, MatTooltipModule, FontAwesomeModule],
})
export class EditPhotoComponent extends EditFileComponent implements OnInit {
  private dialog = inject(MatDialog);

  private readonly defaultImage = "assets/child.png";
  private compression = 480;
  private initialImg: SafeUrl = this.defaultImage;
  readonly imgPath = signal<SafeUrl>(this.defaultImage);

  override async onFileSelected(file: File): Promise<void> {
    const cvs = await resizeImage(file, this.compression);
    this.imgPath.set(cvs.toDataURL());
    const blob = await new Promise<Blob>((res) => cvs.toBlob(res));
    const reducedFile = new File([blob], file.name, {
      type: file.type,
      lastModified: file.lastModified,
    });
    return super.onFileSelected(reducedFile);
  }

  override ngOnInit() {
    this.acceptedFileTypes = "image/*";
    this.compression =
      this.formFieldConfig()?.additional?.imageCompression ?? this.compression;
    super.ngOnInit();
    const entity = this.entity();
    const formFieldConfig = this.formFieldConfig();
    if (this.formControl.value && entity && formFieldConfig) {
      this.fileService.loadFile(entity, formFieldConfig.id).subscribe((res) => {
        this.imgPath.set(res);
        this.initialImg = res;
      });
    }
  }

  override delete() {
    this.resetPreview(this.defaultImage);
    super.delete();
  }

  protected override resetFile() {
    this.resetPreview(this.initialImg);
    super.resetFile();
  }

  private resetPreview(resetImage: SafeUrl) {
    if (this.imgPath() !== this.initialImg) {
      URL.revokeObjectURL(this.imgPath() as string);
    }
    this.imgPath.set(resetImage);
  }

  protected override deleteExistingFile() {
    URL.revokeObjectURL(this.initialImg as string);
    this.initialImg = this.defaultImage;
    super.deleteExistingFile();
  }

  openPopup() {
    this.dialog.open(ImagePopupComponent, { data: { url: this.imgPath() } });
  }
}
<div class="photo-container">
  <img
    [src]="imgPath()"
    i18n-alt
    alt="Image"
    class="image"
    (click)="openPopup()"
  />

  <div
    class="img-controls"
    [matTooltipDisabled]="!(isControlEnabled() && !navigator.onLine)"
    matTooltip="Changes to files are not possible offline."
    i18n-matTooltip
  >
    @if (hasControlValue() && isControlEnabled()) {
      <button
        type="button"
        mat-icon-button
        (click)="delete()"
        i18n-matTooltip="Tooltip remove file"
        matTooltip="Remove file"
        [disabled]="!navigator.onLine"
      >
        <fa-icon icon="xmark"></fa-icon>
      </button>
    }
    @if (isControlEnabled()) {
      <button
        type="button"
        mat-icon-button
        (click)="fileUpload.click()"
        i18n-matTooltip="Tooltip upload file button"
        matTooltip="Upload file"
        [disabled]="!navigator.onLine"
      >
        <fa-icon icon="upload"></fa-icon>
      </button>
    }
  </div>

  <input
    type="file"
    style="display: none"
    (change)="onFileSelected($event.target['files'][0])"
    [accept]="acceptedFileTypes"
    #fileUpload
  />
</div>

./edit-photo.component.scss

@use "variables/colors";

.image {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  object-fit: cover;
  cursor: pointer;
  background: lightgrey;
  display: block;
}

.img-controls {
  display: flex;
  align-items: flex-end;
  height: 48px;
}
.img-label {
  margin: auto;
  color: rgba(0, 0, 0, 0.6);
}
.img-label.invalid {
  color: colors.$error;
}

.photo-container {
  display: flex;
  flex-direction: column;
  align-items: center;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""