All files / src/app/shared/components/common/in-place-edit in-place-edit.component.ts

94.11% Statements 32/34
78.94% Branches 15/19
90% Functions 9/10
94.11% Lines 32/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 852x 2x                         2x 2x 2x               2x   18x   18x 18x 18x   18x 18x     18x 18x 18x         18x     10x 10x     10x       10x 10x 2x   10x 10x 10x 8x             4x     4x 4x       2x 2x       30x      
import { DOCUMENT } from '@angular/common';
import {
  AfterViewInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  DestroyRef,
  ElementRef,
  EventEmitter,
  Inject,
  Input,
  Output,
  inject,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { fromEvent } from 'rxjs';
import { filter, map } from 'rxjs/operators';
 
@Component({
  selector: 'ish-in-place-edit',
  templateUrl: './in-place-edit.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  styleUrls: ['./in-place-edit.component.scss'],
})
export class InPlaceEditComponent implements AfterViewInit {
  // localization key, can be used to give the edit-pen icon a more descriptive aria label that describes what will be edited when clicking it
  @Input() ariaLabelName = '';
  @Input() buttonClass: string;
  @Input() confirmDisabled = false;
  @Output() edited = new EventEmitter<void>();
  @Output() aborted = new EventEmitter<void>();
 
  private mode: 'view' | 'edit' = 'view';
  private destroyRef = inject(DestroyRef);
 
  constructor(
    private host: ElementRef,
    private cdRef: ChangeDetectorRef,
    @Inject(DOCUMENT) private document: Document
  ) {}
 
  // change into edit mode by clicking on the text
  ngAfterViewInit() {
    fromEvent(this.document, 'mousedown')
      .pipe(
        // toggle edit mode only on main button click
        filter((event: MouseEvent) => !event.button),
        map(({ target }) => this.host.nativeElement.contains(target)),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe(click => this.toggleEditMode(click));
  }
 
  toggleEditMode(edit: boolean) {
    const newMode = edit ? 'edit' : 'view';
    if (newMode === 'view' && newMode !== this.mode) {
      this.confirm();
    }
    this.mode = newMode;
    this.cdRef.detectChanges();
    if (this.mode === 'edit') {
      setTimeout(() => {
        this.host.nativeElement.querySelector('.form-control')?.focus();
      }, 200);
    }
  }
 
  confirm() {
    Iif (this.confirmDisabled) {
      return;
    }
    this.mode = 'view';
    this.edited.emit();
  }
 
  cancel() {
    this.mode = 'view';
    this.aborted.emit();
  }
 
  get viewMode() {
    return this.mode === 'view';
  }
}