{"version":3,"file":"dennysjmarquez-ngx-nested-forms.mjs","sources":["../../../projects/ngx-nested-forms/src/lib/ngx-nested-forms.service.ts","../../../projects/ngx-nested-forms/src/lib/ngx-nested-forms.module.ts","../../../projects/ngx-nested-forms/src/public-api.ts","../../../projects/ngx-nested-forms/src/dennysjmarquez-ngx-nested-forms.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { AbstractControl, FormBuilder, FormControl, FormGroup } from '@angular/forms';\nimport { Observable, Subject } from 'rxjs';\nimport { FormEvent } from './models/form-event.interface';\n\n\n/**\n * Service for managing nested forms and their controls.\n *\n * This service solves the problem of managing nested forms between components.\n * It allows centralizing the management of forms and their controls, facilitating interaction\n * between parent, child, and grandchild components within a single main form.\n *\n * **Important, correct usage:** To avoid state sharing problems between different screens,\n * this service must be provided at the main component level of the screen.\n * Child components should inject the service normally to share the same instance.\n * This ensures that each instance of the main component has its own service instance,\n * resetting its state when entering the screen again and maintaining data integrity.\n *\n * @example\n * ```typescript\n * import { Component, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';\n * import { FormBuilder, FormGroup, FormControl, NgForm } from '@angular/forms';\n * import { FormService } from '@dennysjmarquez/ngx-nested-forms';\n * import { Subscription } from 'rxjs';\n *\n * @Component({\n *   selector: 'app-example',\n *   templateUrl: './example.component.html',\n *   providers: [FormService] // Provider at main component level\n * })\n * export class ExampleComponent implements AfterViewInit, OnDestroy {\n *   @ViewChild('f') f!: NgForm;\n *   private formEventSubscription: Subscription;\n *\n *   constructor(private formService: FormService) {}\n *\n *   ngAfterViewInit() {\n *     // Register the form in the service\n *     this.formService.registerRootForms('myForm', this.f);\n *\n *     // Subscribe to service events\n *     this.formEventSubscription = this.formService.getFormEventObservable().subscribe(event => {\n *       console.log('Form event:', event);\n *     });\n *   }\n *\n *   ngOnDestroy() {\n *     // Unsubscribe from observable to avoid memory leaks\n *     if (this.formEventSubscription) {\n *       this.formEventSubscription.unsubscribe();\n *     }\n *   }\n *\n *   // Method to add a control dynamically\n *   addControl() {\n *     const newControl = new FormControl('');\n *     this.formService.registerFormElement('myForm', 'newControl', newControl);\n *   }\n * }\n *\n * @Component({\n *   selector: 'app-child',\n *   templateUrl: './child.component.html',\n * })\n * export class ChildComponent {\n *   constructor(private formService: FormService) {\n *     // Uses the same service instance in children without using providers: [FormService] in child/grandchild components\n *   }\n * }\n * ```\n *\n * @author\n * Author Name: Dennys Jose Marquez Reyes - dennysjmarquez\n * Contact: dennysjmarquez@gmail.com\n * Website: https://dennysjmarquez.dev/\n *\n * @repository\n * Repository URL: https://github.com/dennysjmarquez/angular-nested-forms-service\n */\n@Injectable({\n  providedIn: 'root'\n})\nexport class FormService {\n  private readonly mainForm: FormGroup;\n  private formEventSubject = new Subject<FormEvent>();\n  private eventHistory: FormEvent[] = [];\n\n  constructor(private fb: FormBuilder) {\n    this.mainForm = this.fb.group({});\n  }\n\n  // Public Registration Methods\n\n  /**\n   * Registers a form in the service.\n   *\n   * @param name - Name of the form.\n   * @param formGroup - Instance of the FormGroup representing the form.\n   *\n   * @example\n   * ```typescript\n   * // Using FormGroup\n   * const formGroup = this.fb.group({\n   *   name: new FormControl(''),\n   *   age: new FormControl('')\n   * });\n   * this.formService.registerRootForms('myForm', formGroup);\n   *\n   * // Using NgForm with @ViewChild\n   * @ViewChild('f') f!: NgForm;\n   * this.formService.registerRootForms('myForm', this.f);\n   * ```\n   */\n  registerRootForms(name: string, formGroup: FormGroup): void {\n    this.mainForm.setControl(name, formGroup);\n    const event: FormEvent = { type: 'form', path: name };\n    this.eventHistory.push(event);\n    this.formEventSubject.next(event);\n  }\n\n  /**\n   * Registers a control within a nested form.\n   *\n   * This method allows adding a `FormControl` or `FormGroup` within another `FormGroup`,\n   * at a specific path. It supports the option to overwrite an existing control\n   * and to insert the new control at a specific position within the control order.\n   *\n   * @param path - Path of the nested form in string format (`'form.subForm'`)\n   * or as array (`['form', 'subForm']`).\n   *\n   * @param controlName - Name of the control to register within the target form.\n   *\n   * @param control - Instance of `FormControl`, `FormGroup` or `AbstractControl` to register.\n   *\n   * @param optionsOrOverwrite - (Optional) Can be:\n   * - A boolean `true` to overwrite an existing control (backward compatible mode).\n   * - Options:\n   *   - `overwrite` (boolean): Whether to overwrite an existing control. Default: `false`.\n   *   - `insertAtIndex` (number): Index where to insert the new control, useful for dynamic ordering.\n   *\n   * @returns A `FormEventInterface` object with `{ type: 'formElement', path, control }` if registration was successful,\n   * or `null` if the form was not found.\n   *\n   * @example\n   * ```ts\n   * const newControl = new FormControl('');\n   * formService.registerFormElement(\n   *   ['myForm', 'subForm'],\n   *   'newControl',\n   *   newControl,\n   *   true // Overwrite if exists\n   * );\n   * ```\n   *\n   * @example\n   * ```ts\n   * const newControl = new FormControl('');\n   * formService.registerFormElement(\n   *   'myForm.subForm',\n   *   'newControl',\n   *   newControl,\n   *   { overwrite: true, insertAtIndex: 1 } // Insert in controlled order\n   * );\n   * ```\n   */\n  registerFormElement(\n    path: string | string[],\n    controlName: string,\n    control: FormControl | FormGroup | AbstractControl,\n    optionsOrOverwrite: boolean | { overwrite?: boolean; insertAtIndex?: number } = false\n  ): FormEvent | null {\n    const normalizedPath = this.normalizePath(path);\n    const formGroup = this.getNestedForm(normalizedPath);\n    if (!formGroup) return null;\n\n    const overwrite = typeof optionsOrOverwrite === 'boolean'\n      ? optionsOrOverwrite\n      : optionsOrOverwrite.overwrite ?? false;\n\n    const insertAtIndex = typeof optionsOrOverwrite === 'object'\n      ? optionsOrOverwrite.insertAtIndex\n      : undefined;\n\n    const exists = formGroup.contains(controlName);\n\n    if (!exists || overwrite) {\n      if (exists) {\n        formGroup.removeControl(controlName);\n      }\n\n      if (insertAtIndex !== undefined && insertAtIndex >= 0) {\n        const newControls: { [key: string]: AbstractControl } = {};\n        const keys = Object.keys(formGroup.controls);\n\n        keys.forEach((key, i) => {\n          if (i === insertAtIndex) {\n            newControls[controlName] = control;\n          }\n          newControls[key] = formGroup.controls[key];\n        });\n\n        if (insertAtIndex >= keys.length) {\n          newControls[controlName] = control;\n        }\n\n        Object.keys(formGroup.controls).forEach(k => formGroup.removeControl(k));\n        Object.entries(newControls).forEach(([k, c]) => formGroup.addControl(k, c));\n      } else {\n        formGroup.addControl(controlName, control);\n      }\n\n      const event: FormEvent = {\n        type: 'formElement',\n        path: [...normalizedPath, controlName].join('.'),\n        control\n      };\n      this.eventHistory.push(event);\n      this.formEventSubject.next(event);\n      return event;\n    }\n    return null;\n  }\n\n  /**\n   * Removes a form element at the specified path.\n   * @param path - Form path in format \"form.control\" or as string array.\n   * @returns true if the control was removed, false otherwise.\n   *\n   * @example\n   * ```typescript\n   * this.formService.removeFormElement('myForm.newControl');\n   * ```\n   * @example\n   * ```typescript\n   * this.formService.removeFormElement(['myForm', 'subForm', 'newControl']);\n   * ```\n   */\n  removeFormElement(path: string | string[]): boolean {\n    const keys = this.normalizePath(path);\n    const controlName = keys.pop();\n    const parentGroup = this.getNestedForm(keys);\n    if (parentGroup && controlName && parentGroup.contains(controlName)) {\n      parentGroup.removeControl(controlName);\n      return true;\n    }\n    return false;\n  }\n\n  // Public Retrieval Methods\n\n  /**\n   * Gets a form control at the specified path.\n   * @param path - Form path in format \"form.control\" or as string array.\n   * @returns The control instance (AbstractControl) or null if not found.\n   *\n   * @example\n   * ```typescript\n   * const control = this.formService.getControl('myForm.newControl');\n   * ```\n   * @example\n   * ```typescript\n   * const control = this.formService.getControl(['myForm', 'subForm', 'newControl']);\n   * ```\n   */\n  getControl(path: string | string[]): AbstractControl | null {\n    const keys = this.normalizePath(path);\n    let currentControl: AbstractControl | null = this.mainForm;\n\n    for (const key of keys) {\n      if (currentControl && currentControl.get(key)) {\n        currentControl = currentControl.get(key);\n      } else {\n        return null;\n      }\n    }\n\n    return currentControl;\n  }\n\n  /**\n   * Gets the main form managed by the service.\n   *\n   * @returns The main FormGroup instance.\n   *\n   * @example\n   * ```typescript\n   * const mainForm = this.formService.getForm();\n   * console.log('Main form:', mainForm);\n   * ```\n   */\n  getForm(): FormGroup {\n    return this.mainForm;\n  }\n\n  /**\n   * Gets an observable that emits events when forms or controls are registered.\n   *\n   * Method provided so that child or descendant components of the main component\n   * can register additional forms or controls. This ensures that forms and\n   * controls are fully loaded and available before attempting to add\n   * any additional controls, following the component lifecycle flow.\n   *\n   * A way to ensure that forms and controls are fully loaded and\n   * available before attempting to add any additional controls.\n   * This is achieved through the use of an Observable that emits events when forms\n   * and controls are ready.\n   *\n   * Registration Events:\n   *\n   * - Event Type 'form': Indicates that a new form has been registered. The event.path contains the identifier of the registered form.\n   * - Event Type 'formElement': Indicates that a new control has been registered in a form. The event.path contains the identifier of the form and the registered control in format formPath.controlPath.\n   *\n   * Usage of event.path:\n   *\n   * - For 'form' type events, event.path will be the form identifier, for example, 'mainForm'.\n   * - For 'formElement' type events, event.path will be the form identifier and the control, for example, 'mainForm.newControl'.\n   *\n   * Note:\n   *\n   * It is important to ensure that subscriptions to the observable are destroyed using `ngOnDestroy`\n   * to avoid performance problems or unexpected behavior.\n   *\n   * Additionally, in some specific cases, it may be useful to unsubscribe within the `subscribe`\n   * after performing a specific action to avoid repeated calls. For example, if you only\n   * want to perform an action once when a specific form is registered.\n   *\n   * @returns Observable that emits FormEventInterface type events.\n   *\n   * @example\n   * Example 1: Registering an additional control when a specific form is registered.\n   *\n   * ```typescript\n   * this.formService.getFormEventObservable().subscribe(event => {\n   *   if (event.type === 'form' && event.path === 'form-1') {\n   *     this.formService.registerFormElement(\n   *       'form-1',\n   *       'list',\n   *       new FormControl(this.dataTable)\n   *     );\n   *     this.formEventSubscription$.unsubscribe();\n   *   }\n   * });\n   * ```\n   *\n   * Example 2: Registering an additional control when a specific control is registered in a form.\n   *\n   * ```typescript\n   * this.formService.getFormEventObservable().subscribe(event => {\n   *   if (event.type === 'formElement' && event.path === 'mainForm.existingForm') {\n   *     this.formService.registerFormElement(\n   *       'mainForm.existingForm',\n   *       'newControl',\n   *       new FormControl('')\n   *     );\n   *   }\n   * });\n   * ```\n   */\n  getFormEventObservable(): Observable<FormEvent> {\n    return this.formEventSubject.asObservable();\n  }\n\n  /**\n   * Gets the event history.\n   * Useful for optimization - check if a form is already registered before subscribing.\n   *\n   * @returns Array of all FormEventInterface objects that have occurred.\n   *\n   * @example\n   * ```typescript\n   * const eventHistory = this.formService.getFormEventHistory();\n   * const isParentRegistered = eventHistory.find(\n   *   event => event.type === 'form' && event.path === 'mainForm'\n   * );\n   *\n   * if (isParentRegistered) {\n   *   // Parent is already registered, register immediately\n   *   this.registerChildForm();\n   * } else {\n   *   // Wait for parent registration\n   *   this.formService.getFormEventObservable().subscribe(...);\n   * }\n   * ```\n   */\n  getFormEventHistory(): FormEvent[] {\n    return this.eventHistory;\n  }\n\n  /**\n   * Disables ALL controls of a form, except those indicated in `exceptions`.\n   * Useful for read-only modes or cloning scenarios where only certain fields should be editable.\n   *\n   * @param formPath - Path of the form (e.g., 'form1.form_tab1').\n   * @param exceptions - Array of control names that should remain enabled (e.g., ['id']).\n   *\n   * @example\n   * ```typescript\n   * // Disable all fields except 'status' and 'comments'\n   * this.formService.disableAllExcept('mainForm.personalInfo', ['status', 'comments']);\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // In a cloning scenario, allow only certain fields to be edited\n   * if (this.isClone) {\n   *   this.formService.disableAllExcept('form1.form_tab1', [\n   *     'id',\n   *     'name'\n   *   ]);\n   * }\n   * ```\n   */\n  disableAllExcept(formPath: string, exceptions: string[] = []): void {\n    const form = this.getControl(formPath);\n    if (!(form instanceof FormGroup)) return;\n\n    Object.keys(form.controls).forEach((controlName) => {\n      if (!exceptions.includes(controlName)) {\n        form.get(controlName)?.disable({ emitEvent: false, onlySelf: true });\n      }\n    });\n  }\n\n  // Private Methods\n\n  /**\n   * Gets a nested FormGroup at the specified path.\n   * @param path - Form path in format \"form.control\" or as string array.\n   * @returns The FormGroup instance or null if not found.\n   *\n   * @example\n   * ```typescript\n   * const subForm = this.formService.getNestedForm('myForm.subForm');\n   * ```\n   * @example\n   * ```typescript\n   * const subForm = this.formService.getNestedForm(['myForm', 'subForm']);\n   * ```\n   */\n  private getNestedForm(path: string | string[]): FormGroup | null {\n    const keys = this.normalizePath(path);\n    let currentGroup: FormGroup | null = this.mainForm;\n\n    for (const key of keys) {\n      if (currentGroup && currentGroup.get(key) instanceof FormGroup) {\n        currentGroup = currentGroup.get(key) as FormGroup;\n      } else {\n        return null;\n      }\n    }\n\n    return currentGroup;\n  }\n\n  /**\n   * Normalizes the path to an array of strings.\n   * If the path is a string, it splits it by dots.\n   * If the path is an array, it returns it as is.\n   *\n   * @param path - The form path as string or array.\n   * @returns An array of strings representing the path.\n   */\n  private normalizePath(path: string | string[]): string[] {\n    if (typeof path === 'string') {\n      return path.split('.');\n    }\n    return path;\n  }\n}\n","import { NgModule } from '@angular/core';\n\n@NgModule({\n  declarations: [\n  ],\n  imports: [\n  ],\n  exports: []\n})\nexport class NgxNestedFormsModule { }\n","/*\n * Public API Surface of ngx-nested-forms\n */\n\nexport * from './lib/ngx-nested-forms.service';\nexport * from './lib/ngx-nested-forms.module';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}