import {Component, Input, OnChanges, OnInit} from '@angular/core'; import {FormControl, FormGroup, Validators} from '@angular/forms'; import {Defaults} from '../../constant/defaults.constant'; import {Helper} from '../../helper/helper'; @Component({ selector: 'rss-other', templateUrl: './other.component.html', styleUrls: ['./other.component.scss'] }) export class OtherComponent implements OnInit, OnChanges { @Input() control: FormControl; @Input() label: any; @Input() required: boolean = Defaults.REQUIRED; @Input() requiredError: string = Defaults.REQUIRED_ERROR_MESSAGE; @Input() parentKey: string; @Input() selectedOption: string; @Input() readonly: boolean; @Input() keyword = Defaults.OTHER; @Input() group: FormGroup; @Input() placeholder = Defaults.PLACEHOLDER; @Input() inputType: string; @Input() dropdownOptions: any; @Input() url: any; @Input() parentDisplayKey: string = Defaults.DISPLAY_KEY; @Input() textConfig = {type: 'text'}; @Input() dropdownPlaceholder = Defaults.PLACEHOLDER; @Input() excludeValidators: boolean; constructor() { } ngOnInit() { if (!this.control) { console.error(Defaults.MISSING_FORM_CONTROL_ERROR_MESSAGE); } this.initialize(); } initialize() { if (!this.textConfig || !this.textConfig.type) { this.textConfig = {type: 'text'}; } this.initializeParentDisplayKey(); this.initializeControl(); this.selectedOption = this.getParentValue(); this.initializeValidators(); } initializeParentDisplayKey() { if (!this.parentDisplayKey) { this.parentDisplayKey = Defaults.DISPLAY_KEY; } } initializeControl() { if (!this.showInputBox() && !this.getParentValue() && !this.showDropdown()) { this.control.reset(); } } getParentValue() { // Currently supports parents of type: // multi-select checkboxes // multi selectable dropdowns // simple dropdowns let selectedOption = null; const parentValue = this.group.controls[this.parentKey].value; if (Helper.isArray(parentValue)) { const itemFound = parentValue.find(item => item[this.parentDisplayKey] === this.keyword); if (itemFound) { selectedOption = itemFound[this.parentDisplayKey]; } } else if (parentValue) { selectedOption = parentValue[this.parentDisplayKey]; } return selectedOption; } initializeValidators() { if (this.control && this.selectedOption && this.selectedOption === this.keyword && !this.excludeValidators) { this.control.setValidators(Validators.required); } else { this.control.clearValidators(); } } ngOnChanges() { // when the controls are reset, do reset the selectedOption as well if ((!this.control || !this.control.value) && (!this.group.controls[this.parentKey] || !this.getParentValue())) { this.selectedOption = ''; } // Subscribe to the changes of its parent this.group.controls[this.parentKey].valueChanges.subscribe((value) => { this.initialize(); if (value && value !== this.keyword && this.control.touched) { this.control.reset(); } }); } showOther() { return this.selectedOption && this.selectedOption === this.keyword; } showInputBox() { return (this.showOther() && this.inputType === 'textbox'); } showDropdown() { return (this.showOther() && this.inputType === 'dropdown'); } displayRequiredError(fc: FormControl) { if (this.selectedOption && this.selectedOption === this.keyword) { const validator = fc ? !this.control.value : false; if (validator && !this.excludeValidators) { this.control.setErrors(Validators.requiredTrue); } return validator; } } }