File

libs/acl/angular/src/lib/policy-editor/editable/editable.component.ts

Description

via Keeping It Simple: Implementing Edit-in-Place in Angular https://netbasal.com/keeping-it-simple-implementing-edit-in-place-in-angular-4fd92c4dfc70

Modified & Adapted to our needs

Implements

OnInit

Metadata

Index

Properties
Methods
Outputs
HostListeners
Accessors

Constructor

constructor(host: ElementRef)
Parameters :
Name Type Optional
host ElementRef No

Outputs

editComplete
Type : EventEmitter
editStart
Type : EventEmitter

HostListeners

keyup.enter
keyup.enter()

Methods

onEnter
onEnter()
Decorators :
@HostListener('keyup.enter')
Returns : void
toEditMode
toEditMode()
Returns : void
toViewMode
toViewMode()
Returns : void

Properties

editMode
Default value : new Subject<boolean>()
editMode$
Default value : this.editMode.asObservable()
editModeTpl
Type : EditModeDirective
Decorators :
@ContentChild(EditModeDirective)
mode
Type : "view" | "edit"
Default value : 'view'
viewModeTpl
Type : ViewModeDirective
Decorators :
@ContentChild(ViewModeDirective)

Accessors

currentView
getcurrentView()
import {
  Component,
  ContentChild,
  DestroyRef,
  ElementRef,
  EventEmitter,
  HostListener,
  OnInit,
  Output,
  inject
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Subject, fromEvent } from 'rxjs';
import { filter, switchMapTo, take } from 'rxjs/operators';
import { EditModeDirective } from './edit-mode.directive';
import { ViewModeDirective } from './view-mode.directive';

/**
 * via Keeping It Simple: Implementing Edit-in-Place in Angular
 * https://netbasal.com/keeping-it-simple-implementing-edit-in-place-in-angular-4fd92c4dfc70
 *
 * Modified & Adapted to our needs
 */
@Component({
  selector: 'acl-editable',
  template: ` <ng-container *ngTemplateOutlet="currentView"></ng-container> `,
  styles: [
    `
      :host {
        width: 100%;
      }
    `
  ],
  standalone: false
})
export class EditableComponent implements OnInit {
  @Output() editComplete = new EventEmitter<void>();
  @Output() editStart = new EventEmitter();
  @ContentChild(ViewModeDirective) viewModeTpl!: ViewModeDirective;
  @ContentChild(EditModeDirective) editModeTpl!: EditModeDirective;

  mode: 'view' | 'edit' = 'view';

  editMode = new Subject<boolean>();
  editMode$ = this.editMode.asObservable();

  private destroyRef = inject(DestroyRef);

  constructor(private host: ElementRef) {}

  get currentView() {
    return this.mode === 'view' ? this.viewModeTpl.tpl : this.editModeTpl.tpl;
  }

  ngOnInit() {
    this.viewModeHandler();
    this.editModeHandler();
  }

  private get parentElement() {
    return this.host.nativeElement.parentElement;
  }

  private viewModeHandler() {
    fromEvent(this.parentElement, 'dblclick')
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(() => {
        this.toEditMode();
      });
  }

  private editModeHandler() {
    const clickOutside$ = fromEvent(document, 'click').pipe(
      filter(({ target }) => this.parentElement.contains(target) === false),
      take(1)
    );

    this.editMode$
      .pipe(switchMapTo(clickOutside$), takeUntilDestroyed(this.destroyRef))
      .subscribe(() => {
        this.editComplete.next();
        this.mode = 'view';
      });
  }

  toEditMode() {
    this.mode = 'edit';
    this.editMode.next(true);
    this.editStart.emit();
  }

  toViewMode() {
    this.mode = 'view';
    this.editComplete.next();
  }

  @HostListener('keyup.enter')
  onEnter() {
    this.toViewMode();
  }
}

      :host {
        width: 100%;
      }
    
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""