import { Component, OnInit, Input, Output, EventEmitter, OnDestroy, AfterViewInit } from '@angular/core'; import { BehaviorSubject, Subscription } from 'rxjs'; import { FormGroup, FormBuilder } from '@angular/forms'; import { Router, NavigationEnd } from '@angular/router'; @Component({ selector: 'os-extension-field', templateUrl: './extension-field.component.html', styleUrls: ['./extension-field.component.scss'] }) export class ExtensionFieldComponent implements OnInit, OnDestroy, AfterViewInit { /** * Optional additional classes for the `mat-chip`. */ @Input() public classes: string | string[] | object = 'bluegrey'; /** * Title for this component. */ @Input() public title: string; /** * Value of the chip. */ @Input() public chipValue: string; /** * Allow automatically jump into autoEdit */ private allowAutoEdit = false; /** * Boolean, whether the extension should be shown. */ private _hasExtension = false; /** * Setter for the extension condition */ @Input() public set hasExtension(extension: boolean) { this._hasExtension = extension; if (this.hasExtension && this.allowAutoEdit) { this.editMode = true; } } /** * Getter for the extension condition */ public get hasExtension(): boolean { return this._hasExtension; } /** * Optional label for the input. */ @Input() public extensionLabel: string; /** * Optional label for the search-list. */ @Input() public searchListLabel: string; /** * BehaviourSubject for the search-list. */ @Input() public searchList: BehaviorSubject; /** * Boolean, whether the input and the search-list can be changed. */ @Input() public canBeEdited = true; /** * Boolean, whether the list should fire events, if it changes. */ @Input() public listSubmitOnChange = false; /** * Boolean, whether to append the value from list to the input. */ @Input() public appendValueToInput = true; /** * Prefix, if the value from list should be appended to the input. */ @Input() public listValuePrefix = ''; /** * Suffix, if the value from list should be appended to the input. */ @Input() public listValueSuffix = ''; /** * Initial value of the input-field. */ @Input() public inputValue: string; /** * EventEmitter, when clicking on the 'save'-button. */ @Output() public success: EventEmitter = new EventEmitter(); /** * EventEmitter, if the list has changed. */ @Output() public listChange: EventEmitter = new EventEmitter(); /** * Model for the input-field. */ public inputControl = ''; /** * FormGroup for the search-list. */ public extensionFieldForm: FormGroup; /** * Boolean to decide, whether to open the extension-input and search-list. */ public editMode = false; /** * Hold the nav subscription */ private navigationSubscription: Subscription; /** * Subscription for the search value selector */ private searchValueSubscription: Subscription; /** * Constructor * * @param fb The FormBuilder */ public constructor(private fb: FormBuilder, private router: Router) {} /** * OnInit-method. */ public ngOnInit(): void { this.navigationSubscription = this.router.events.subscribe(navEvent => { if (navEvent instanceof NavigationEnd) { this.editMode = false; if (this.extensionFieldForm) { this.extensionFieldForm.reset(); } } }); this.initInput(); if (this.searchList) { this.extensionFieldForm = this.fb.group({ list: [[]] }); this.searchValueSubscription = this.extensionFieldForm .get('list') .valueChanges.subscribe((value: number) => { if (!!value) { if (this.listSubmitOnChange) { this.listChange.emit(value); } if (this.appendValueToInput) { if (!this.inputControl) { this.inputControl = ''; } this.inputControl += `[${this.listValuePrefix}${value}${this.listValueSuffix}]`; } this.extensionFieldForm.reset(); } }); } } /** * After view inits, allow to automatically open the edit view */ public ngAfterViewInit(): void { this.allowAutoEdit = true; } /** * On destroy unsubscribe from the subscriptions */ public ngOnDestroy(): void { this.navigationSubscription.unsubscribe(); if (this.searchValueSubscription) { this.searchValueSubscription.unsubscribe(); } } /** * Hitting enter on the input field should save the content */ public keyDownFunction(event: any): void { if (event.key === 'Enter') { this.changeEditMode(true); } } /** * Function to switch to or from editing-mode. * * @param save Boolean, whether the changes should be saved or resetted. */ public changeEditMode(save: boolean = false): void { if (save) { this.sendSuccess(); } else { this.initInput(); } this.editMode = !this.editMode; } /** * Initialize the value of the input. */ public initInput(): void { this.inputControl = this.inputValue; } /** * Function to execute, when the values are saved. */ public sendSuccess(): void { if (this.success) { const submitMessage = this.listSubmitOnChange || this.appendValueToInput || !this.searchList ? this.inputControl : { extensionInput: this.inputControl, extensionList: this.extensionFieldForm.get('list').value }; this.success.emit(submitMessage); } } }