UNPKG

@rxap/form-system

Version:

This package provides a set of directives, decorators, mixins, and validators to simplify the creation of dynamic forms in Angular applications. It offers features such as automatic control creation, data source integration, component customization, and h

1 lines 146 kB
{"version":3,"file":"rxap-form-system.mjs","sources":["../../../../../packages/angular/form-system/src/lib/validators/is-equal-to.ts","../../../../../packages/angular/form-system/src/lib/decorators/metadata-keys.ts","../../../../../packages/angular/form-system/src/lib/decorators/use-data-source.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-control.mixin.ts","../../../../../packages/angular/form-system/src/lib/error.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-data-sources.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-form-definition.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-options-data-source.mixin.ts","../../../../../packages/angular/form-system/src/lib/validators/is-selectable-value.directive.ts","../../../../../packages/angular/form-system/src/lib/mixins/adapters.ts","../../../../../packages/angular/form-system/src/lib/mixins/apply-use-function.adapters.ts","../../../../../packages/angular/form-system/src/lib/mixins/apply-use-method.adapters.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-control-from-parent.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-functions.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-function.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-is-value-function.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-methods.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-method.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-options-method.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-resolve-method.mixin.ts","../../../../../packages/angular/form-system/src/lib/mixins/extract-to-display-function.mixin.ts","../../../../../packages/angular/form-system/src/lib/directives/array/for-form-array-items.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/array/form-array-add-item-button.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/array/form-array-item-button.ts","../../../../../packages/angular/form-system/src/lib/directives/array/form-array-item-remove-button.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/array/form-array-item-restore-button.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/array/form-array-removable.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/options-from-method.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/autocomplete-options-from-method.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/control-hide-show.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/input-select-options.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/form-directives.module.ts","../../../../../packages/angular/form-system/src/lib/directives/options-from-remote-method.directive.ts","../../../../../packages/angular/form-system/src/lib/directives/test-ng-control.ts","../../../../../packages/angular/form-system/src/lib/decorators/use-component.ts","../../../../../packages/angular/form-system/src/lib/decorators/use-form-component.ts","../../../../../packages/angular/form-system/src/lib/control-data-source.ts","../../../../../packages/angular/form-system/src/lib/form-context-from-activated-route.factory.ts","../../../../../packages/angular/form-system/src/lib/form-system-control.directive.ts","../../../../../packages/angular/form-system/src/lib/submit-context-form-adapter.factory.ts","../../../../../packages/angular/form-system/src/index.ts","../../../../../packages/angular/form-system/src/rxap-form-system.ts"],"sourcesContent":["import {\n Directive,\n forwardRef,\n Input,\n} from '@angular/core';\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from '@angular/forms';\nimport { Required } from '@rxap/utilities';\n\n@Directive({\n selector: '[rxapIsEqualTo]',\n providers: [\n {\n provide: NG_VALIDATORS,\n multi: true,\n useExisting: forwardRef(() => IsEqualToDirective),\n },\n ],\n standalone: true,\n})\nexport class IsEqualToDirective implements Validator {\n\n @Input({\n required: true,\n alias: 'rxapIsEqualTo',\n })\n public set equalTo(value: any) {\n this._equalTo = value;\n if (this._onChange) {\n this._onChange();\n }\n }\n\n private _onChange!: () => void;\n\n\n private _equalTo!: any;\n\n public validate(control: AbstractControl): ValidationErrors | null {\n if (this._equalTo === null || this._equalTo === control.value) {\n return null;\n }\n return {\n isEqualTo: {\n value: this._equalTo,\n actualValue: control.value,\n },\n };\n }\n\n /**\n * @description\n * Registers a callback function to call when the validator inputs change.\n *\n * @param fn The callback function\n */\n public registerOnValidatorChange(fn: () => void): void {\n this._onChange = fn;\n }\n\n}\n\n\n","export enum FormSystemMetadataKeys {\n COMPONENTS = 'rxap/form-system/components',\n DATA_SOURCES = 'rxap/form-system/data-sources',\n COMPONENTS_PROPERTIES = 'rxap/form-system/components-properties',\n FORM_COMPONENT = 'rxap/window-form-system/form-component',\n}\n","import { BaseDataSource } from '@rxap/data-source';\nimport { FormSystemMetadataKeys } from './metadata-keys';\nimport { IdOrInstanceOrToken } from '@rxap/definition';\nimport { setMetadataMapMap } from '@rxap/reflect-metadata';\n\nexport interface UseDataSourceSettings<Source = any, Target = Source> {\n transformer?: (source: Source) => Target;\n}\n\nexport interface UseDataSourceValue<Source = any, Target = Source> {\n dataSource: IdOrInstanceOrToken<BaseDataSource>,\n settings?: UseDataSourceSettings<Source, Target>,\n\n /**\n * The last value of the data source\n */\n lastValue?: Target,\n}\n\nexport function UseDataSource<Data>(\n dataSource: IdOrInstanceOrToken<BaseDataSource<Data>>,\n name: string,\n settings?: UseDataSourceSettings,\n) {\n return function (target: any, propertyKey: string) {\n const value: UseDataSourceValue<Data> = {\n dataSource,\n settings,\n };\n setMetadataMapMap(propertyKey, name, value, FormSystemMetadataKeys.DATA_SOURCES, target);\n };\n}\n","import {\n AbstractControlDirective,\n NgControl,\n} from '@angular/forms';\nimport { MatFormField } from '@angular/material/form-field';\nimport { RxapFormControl } from '@rxap/forms';\n\nexport class ExtractControlMixin {\n\n protected ngControl!: NgControl | AbstractControlDirective | null;\n\n protected matFormField?: MatFormField | null;\n\n protected control?: RxapFormControl;\n\n protected extractControl(ngControl: NgControl | AbstractControlDirective | null = this.ngControl ??\n this.matFormField?._control?.ngControl ??\n null): RxapFormControl {\n\n if (!ngControl) {\n throw new Error('The ngControl is not defined!');\n }\n\n this.ngControl = ngControl;\n\n const control = this.ngControl.control;\n\n if (!(control instanceof RxapFormControl)) {\n throw new Error('Control is not a RxapFormControl!');\n }\n\n return this.control = control;\n }\n\n}\n","import { RxapError } from '@rxap/utilities';\n\nexport class RxapFormSystemError extends RxapError {\n\n constructor(message: string, code: string, className?: string) {\n super('@rxap/form-system', message, code, className);\n }\n\n}\n","import { FormDefinition } from '@rxap/forms';\nimport { RxapFormSystemError } from '../error';\nimport { FormSystemMetadataKeys } from '../decorators/metadata-keys';\nimport { UseDataSourceValue } from '../decorators/use-data-source';\nimport { getMetadata } from '@rxap/reflect-metadata';\n\nexport class ExtractDataSourcesMixin {\n\n protected extractDataSources(formDefinition: FormDefinition, controlId: string): Map<string, UseDataSourceValue> {\n const map = getMetadata<Map<string, Map<string, UseDataSourceValue>>>(\n FormSystemMetadataKeys.DATA_SOURCES,\n Object.getPrototypeOf(formDefinition),\n );\n\n if (!map) {\n throw new RxapFormSystemError('Could not extract the use data source map from the form definition instance', '');\n }\n\n if (!map.has(controlId)) {\n throw new RxapFormSystemError('A use data source definition does not exists in the form definition metadata', '');\n }\n\n return map.get(controlId)!;\n }\n\n}\n","import {\n AbstractControl,\n FormDefinition,\n} from '@rxap/forms';\nimport { RxapFormSystemError } from '../error';\n\nexport class ExtractFormDefinitionMixin {\n\n // TODO : change to AbstractControl from @rxap/forms\n protected extractFormDefinition(control: AbstractControl): FormDefinition {\n const formDefinition = control.rxapFormDefinition;\n\n if (!formDefinition) {\n throw new RxapFormSystemError('Could not find the form definition instance', '');\n }\n\n return formDefinition;\n }\n\n}\n","import {\n Injector,\n isDevMode,\n} from '@angular/core';\nimport { AbstractControl } from '@angular/forms';\nimport {\n BaseDataSource,\n BaseDataSourceMetadata,\n BaseDataSourceViewer,\n DataSourceLoader,\n PipeDataSource,\n} from '@rxap/data-source';\nimport { IdOrInstanceOrToken } from '@rxap/definition';\nimport { RxapFormControl } from '@rxap/forms';\nimport { Mixin } from '@rxap/mixin';\nimport { ControlOptions } from '@rxap/utilities';\nimport {\n map,\n tap,\n} from 'rxjs/operators';\nimport {\n UseDataSource,\n UseDataSourceSettings,\n UseDataSourceValue,\n} from '../decorators/use-data-source';\nimport { InputSelectOptionsSettings } from '../directives/input-select-options.directive';\nimport { ExtractControlMixin } from './extract-control.mixin';\nimport { ExtractDataSourcesMixin } from './extract-data-sources.mixin';\nimport { ExtractFormDefinitionMixin } from './extract-form-definition.mixin';\n\nexport type UseOptionsDataSourceSettings<Source> = UseDataSourceSettings<Source, ControlOptions | Record<string, any>>\n\nexport const DATA_SOURCE_NAME = 'options';\n\nexport function ComposeOptionsTransformers(...fnc: Array<(value: any) => any>): (value: any) => any {\n return base => fnc.reduce((source, transform) => transform(source), base);\n}\n\nexport function UseOptionsDataSource<Source>(\n dataSource: IdOrInstanceOrToken<BaseDataSource<Source>>,\n settings?: InputSelectOptionsSettings<Source>,\n): (\n target: any,\n propertyKey: string,\n) => any;\nexport function UseOptionsDataSource(\n dataSource: IdOrInstanceOrToken<BaseDataSource>,\n settings?: InputSelectOptionsSettings<ControlOptions>,\n) {\n return function (target: any, propertyKey: string) {\n UseDataSource(dataSource, DATA_SOURCE_NAME, settings)(target, propertyKey);\n };\n}\n\nexport interface ExtractOptionsDataSourceMixin extends ExtractFormDefinitionMixin, ExtractDataSourcesMixin,\n ExtractControlMixin {\n}\n\n@Mixin(ExtractControlMixin, ExtractFormDefinitionMixin, ExtractDataSourcesMixin)\nexport class ExtractOptionsDataSourceMixin {\n\n protected settings?: UseOptionsDataSourceSettings<any>;\n\n protected readonly dataSourceLoader!: DataSourceLoader;\n\n protected metadata?: BaseDataSourceMetadata;\n\n protected viewer?: BaseDataSourceViewer;\n\n protected dataSource?: BaseDataSource<ControlOptions | Record<string, any>>;\n\n protected readonly injector!: Injector;\n\n protected useDataSourceValue?: UseDataSourceValue<ControlOptions | Record<string, any>>;\n\n protected extractOptionsDatasource(control?: AbstractControl): BaseDataSource<ControlOptions | Record<string, any>> {\n control ??= this.extractControl();\n\n if (!(control instanceof RxapFormControl)) {\n throw new Error('Ensure to use a RxapFromControl');\n }\n\n const formDefinition = this.extractFormDefinition(control);\n\n const useDataSourceValueMap = this.extractDataSources(formDefinition, control.controlId);\n\n if (!useDataSourceValueMap.has('options')) {\n throw new Error(`The data source with the name 'options' is not defined`);\n }\n\n const useDataSourceValue = this.useDataSourceValue = useDataSourceValueMap.get('options')!;\n\n this.settings = this.useDataSourceValue.settings ?? {};\n\n let dataSource: BaseDataSource;\n\n try {\n\n dataSource = this.dataSourceLoader.load(\n useDataSourceValue.dataSource,\n this.metadata,\n this.injector,\n );\n\n } catch (e: any) {\n\n if (e.name && e.name === 'NullInjectorError') {\n if (isDevMode()) {\n console.error('Cloud not inject the options data source', this.useDataSourceValue);\n }\n throw new Error('Cloud not inject the options data source:\\n' + e.message);\n }\n\n throw e;\n\n }\n\n if (this.settings?.transformer) {\n dataSource = new PipeDataSource(\n dataSource,\n map(this.settings.transformer),\n tap(options => useDataSourceValue.lastValue = options),\n );\n } else {\n dataSource = new PipeDataSource(\n dataSource,\n tap(options => useDataSourceValue.lastValue = options),\n );\n }\n\n return this.dataSource = dataSource;\n }\n\n}\n","import {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from '@angular/forms';\nimport {\n Directive,\n forwardRef,\n Inject,\n INJECTOR,\n Injector,\n Input,\n isDevMode,\n} from '@angular/core';\nimport {\n BaseDataSourceViewer,\n DataSourceLoader,\n} from '@rxap/data-source';\nimport { Mixin } from '@rxap/mixin';\nimport { ControlOptions } from '@rxap/utilities';\nimport { ExtractOptionsDataSourceMixin } from '../mixins/extract-options-data-source.mixin';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface IsSelectableValueDirective extends ExtractOptionsDataSourceMixin {\n}\n\n@Mixin(ExtractOptionsDataSourceMixin)\n@Directive({\n selector: '[rxapIsSelectableValue]',\n providers: [\n {\n provide: NG_VALIDATORS,\n multi: true,\n useExisting: forwardRef(() => IsSelectableValueDirective),\n },\n ],\n standalone: true,\n})\nexport class IsSelectableValueDirective implements Validator {\n\n @Input()\n public viewer: BaseDataSourceViewer = { id: '[rxapIsSelectableValue]' };\n\n constructor(\n @Inject(DataSourceLoader)\n protected readonly dataSourceLoader: DataSourceLoader,\n @Inject(INJECTOR)\n protected readonly injector: Injector,\n ) {\n }\n\n public validate(control: AbstractControl): ValidationErrors | null {\n if (control.value) {\n this.extractOptionsDatasource(control);\n const data = this.useDataSourceValue?.lastValue;\n if (data) {\n let options: ControlOptions;\n if (Array.isArray(data)) {\n options = data;\n } else {\n options = Object.entries(data)\n .map(([ value, display ]) => ({\n value,\n display,\n }));\n }\n if (!options.some(option => option.value === control.value)) {\n return {\n isSelectableValue: {\n expected: 'Value should be from the list of provided options',\n },\n };\n }\n } else if (isDevMode()) {\n console.warn('The last value from the OptionsDataSource is empty', this);\n }\n }\n return null;\n }\n\n}\n\n\n","import { ControlOption } from '@rxap/utilities';\n\nexport function ResolveByUuidParameter({value}: { value: string }) {\n return {\n parameters: {\n uuid: value,\n },\n };\n}\n\nexport function ResolveByUuidResultFactory<Entity>(transformer: (entity: Entity) => ControlOption) {\n return (entity: Entity) => {\n return transformer(entity);\n };\n}\n","import {\n Injector,\n runInInjectionContext,\n} from '@angular/core';\nimport {\n isPromise,\n isPromiseLike,\n} from '@rxap/utilities';\nimport {\n UseFunctionConfig,\n UseFunctionType,\n} from './extract-functions.mixin';\n\nexport function ApplyUseFunctionAdapters<Args extends any[], Result>(injector: Injector, fnc: UseFunctionType<any[], any>, config?: UseFunctionConfig) {\n if (config?.adapter?.result || config?.adapter?.args) {\n return function (this: any, ...args: any[]) {\n return new Promise((resolve, reject) => {\n runInInjectionContext(injector, () => {\n\n args = config?.adapter?.args?.(args) ?? args;\n const result = fnc.call(this, ...(args as Args));\n if (isPromiseLike(result)) {\n const p = result.then((result: any) => {\n resolve(config?.adapter?.result?.(result) ?? result);\n });\n if (isPromise(p)) {\n p.catch(reject);\n }\n } else {\n try {\n resolve(config?.adapter?.result?.(result) ?? result);\n } catch (e) {\n reject(e);\n }\n }\n });\n\n });\n\n };\n }\n return fnc;\n}\n","import {\n Injector,\n runInInjectionContext,\n} from '@angular/core';\nimport {\n Method,\n ToMethod,\n} from '@rxap/pattern';\nimport { isPromiseLike, isPromise } from '@rxap/utilities';\nimport { UseMethodConfig } from './extract-methods.mixin';\n\nexport function ApplyUseMethodAdapters(injector: Injector, method: Method, config?: UseMethodConfig) {\n if (config?.adapter?.result || config?.adapter?.parameter) {\n return ToMethod((parameter: any, ...args: any[]) => {\n return new Promise((resolve, reject) => {\n runInInjectionContext(injector, () => {\n\n parameter = config?.adapter?.parameter?.(parameter) ?? parameter;\n const result = method.call(parameter, ...args);\n if (isPromiseLike(result)) {\n const p = result.then((result: any) => {\n resolve(config?.adapter?.result?.(result) ?? result);\n });\n if (isPromise(p)) {\n p.catch(reject);\n }\n } else {\n try {\n resolve(config?.adapter?.result?.(result) ?? result);\n } catch (e) {\n reject(e);\n }\n }\n });\n\n });\n\n });\n }\n return method;\n}\n","import { ControlContainer } from '@angular/forms';\nimport {\n AbstractControl,\n RxapFormArray,\n RxapFormControl,\n RxapFormGroup,\n} from '@rxap/forms';\nimport { RxapFormSystemError } from '../error';\n\nexport class ExtractControlFromParentMixin {\n\n protected extractControlFromParent(parent: ControlContainer, controlPath: string): AbstractControl {\n if (!controlPath) {\n throw new RxapFormSystemError('The control path is empty', '');\n }\n\n if (!parent.control) {\n throw new RxapFormSystemError('The control property of ControlContainer is not defined', '');\n }\n\n const control = parent.control.get(controlPath);\n\n if (!control) {\n throw new RxapFormSystemError('Could not find the control instance', '');\n }\n\n if (!(control instanceof RxapFormControl) &&\n !(control instanceof RxapFormGroup) &&\n !(control instanceof RxapFormArray)) {\n throw new RxapFormSystemError('The extracted control is not a RxapFormControl', '');\n }\n\n return control;\n }\n\n}\n","import { FormDefinition } from '@rxap/forms';\nimport {\n getMetadata,\n setMetadataMapMap,\n} from '@rxap/reflect-metadata';\n\nexport const RXAP_USE_FUNCTION = 'rxap/form-system/function/use';\n\nexport type FunctionParameterAdapterFunction<Source extends any[] = any[], Target extends any[] = any[]> = (args: Source) => Target;\nexport type FunctionResultAdapterFunction<Source = unknown, Target = unknown> = (result: Source) => Target;\n\nexport interface UseFunctionConfig<\n ReturnTypeTarget = any,\n ArgsSource extends any[] = any[],\n ReturnTypeSource = any,\n ArgsTarget extends any[] = any[],\n> {\n adapter?: {\n args?: FunctionParameterAdapterFunction<ArgsSource, ArgsTarget>;\n result?: FunctionResultAdapterFunction<ReturnTypeSource, ReturnTypeTarget>;\n };\n}\n\nexport type UseFunctionType<Args extends any[], Result> = (...args: Args) => Result\n\nexport function UseFunction<Args extends any[], Result>(fnc: UseFunctionType<Args, Result>, name: string, config?: UseFunctionConfig) {\n return function (target: any, propertyKey: string) {\n setMetadataMapMap(propertyKey, name, {fnc, config}, RXAP_USE_FUNCTION, target);\n };\n}\n\nexport interface UseFunctionDefinition<\n ReturnType = unknown,\n Args extends any[] = any[],\n Config extends UseFunctionConfig<ReturnType, Args> = UseFunctionConfig<ReturnType, Args>\n> {\n fnc: UseFunctionType<Args, ReturnType>;\n config?: Config;\n}\n\nexport class ExtractFunctionsMixin {\n\n protected extractFunctions(\n defaultMap: Map<string, UseFunctionDefinition> | null = null,\n formDefinition: FormDefinition,\n controlId: string,\n ): Map<string, UseFunctionDefinition> {\n const map = getMetadata<Map<string, Map<string, UseFunctionDefinition>>>(\n RXAP_USE_FUNCTION,\n Object.getPrototypeOf(formDefinition),\n );\n\n if (!map) {\n if (defaultMap) {\n return defaultMap;\n }\n throw new Error(\n 'Could not extract the use remote function map from the form definition instance',\n );\n }\n\n if (!map.has(controlId)) {\n if (defaultMap) {\n return defaultMap;\n }\n throw new Error(\n 'A use remote function definition does not exists in the form definition metadata',\n );\n }\n\n return map.get(controlId)!;\n }\n\n}\n","import { Injector } from '@angular/core';\nimport { FormDefinition } from '@rxap/forms';\nimport { Mixin } from '@rxap/mixin';\nimport { ApplyUseFunctionAdapters } from './apply-use-function.adapters';\nimport {\n ExtractFunctionsMixin,\n UseFunctionDefinition,\n UseFunctionType,\n} from './extract-functions.mixin';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface ExtractFunctionMixin extends ExtractFunctionsMixin {\n}\n\n@Mixin(ExtractFunctionsMixin)\nexport class ExtractFunctionMixin {\n\n protected injector!: Injector;\n\n extractFunction<Args extends any[], Result>(\n defaultFunction: UseFunctionType<Args, Result> | null = null,\n formDefinition: FormDefinition,\n controlId: string,\n name: string,\n ): UseFunctionType<Args, Result> {\n const map = this.extractFunctions(new Map<string, UseFunctionDefinition>, formDefinition, controlId);\n if (!map.has(name)) {\n if (defaultFunction) {\n return defaultFunction;\n }\n throw new Error(\n `A function with the name '${ name }' is not attached to the control '${ controlId }' use the @UseFunction decorator to attach a function to the control`);\n }\n const {fnc, config} = map.get(name)!;\n return ApplyUseFunctionAdapters<Args, Result>(this.injector, fnc, config);\n }\n\n}\n","import { RxapFormControl } from '@rxap/forms';\nimport { Mixin } from '@rxap/mixin';\nimport { ExtractControlMixin } from './extract-control.mixin';\nimport { ExtractFormDefinitionMixin } from './extract-form-definition.mixin';\nimport { ExtractFunctionMixin } from './extract-function.mixin';\nimport {\n UseFunction,\n UseFunctionConfig,\n UseFunctionType,\n} from './extract-functions.mixin';\nimport { UseMethodConfig } from './extract-methods.mixin';\n\nexport const IS_VALUE_FUNCTION_NAME = 'is-value';\n\nexport function UseIsValueFunction(\n fnc: UseFunctionType<[any], boolean>,\n): any;\nexport function UseIsValueFunction(\n fnc: UseFunctionType<any[], any>,\n config: UseFunctionConfig<boolean, any[], any, [any]>,\n): any;\nexport function UseIsValueFunction(\n fnc: UseFunctionType<[any], boolean>,\n config?: UseMethodConfig,\n) {\n return function (target: any, propertyKey: string) {\n UseFunction(fnc, IS_VALUE_FUNCTION_NAME, config)(target, propertyKey);\n };\n}\n\nexport interface ExtractIsValueFunctionMixin extends ExtractFormDefinitionMixin, ExtractFunctionMixin,\n ExtractControlMixin {\n}\n\n@Mixin(ExtractFormDefinitionMixin, ExtractFunctionMixin, ExtractControlMixin)\nexport class ExtractIsValueFunctionMixin {\n\n protected extractIsValueFunction(\n defaultFunction: UseFunctionType<[any], boolean> | null = null,\n control: RxapFormControl = this.extractControl(),\n formDefinition = this.extractFormDefinition(control),\n ): UseFunctionType<[any], boolean> {\n return this.extractFunction(defaultFunction, formDefinition, control.controlId, IS_VALUE_FUNCTION_NAME);\n }\n\n}\n","import { ProviderToken } from '@angular/core';\nimport { FormDefinition } from '@rxap/forms';\nimport { Method } from '@rxap/pattern';\nimport {\n getMetadata,\n setMetadataMapMap,\n} from '@rxap/reflect-metadata';\n\nexport const RXAP_USE_METHOD = 'rxap/form-system/method/use';\n\nexport type MethodParameterAdapterFunction<Source = unknown, Target = unknown> = (parameter: Source) => Target;\nexport type MethodResultAdapterFunction<Source = unknown, Target = unknown> = (result: Source) => Target;\n\nexport interface UseMethodConfig<\n ReturnTypeTarget = any,\n ParameterSource = any,\n ReturnTypeSource = any,\n ParameterTarget = any,\n> {\n adapter?: {\n parameter?: MethodParameterAdapterFunction<ParameterSource, ParameterTarget>;\n result?: MethodResultAdapterFunction<ReturnTypeSource, ReturnTypeTarget>;\n };\n}\n\nexport function UseMethod(method: ProviderToken<Method>, name: string, config?: UseMethodConfig) {\n return function (target: any, propertyKey: string) {\n setMetadataMapMap(propertyKey, name, {method, config}, RXAP_USE_METHOD, target);\n };\n}\n\nexport interface UseMethodDefinition<\n ReturnType = unknown,\n Parameter = unknown,\n Config extends UseMethodConfig<ReturnType, Parameter> = UseMethodConfig<ReturnType, Parameter>\n> {\n method: ProviderToken<Method<ReturnType, Parameter>>;\n config?: Config;\n}\n\nexport class ExtractMethodsMixin {\n\n protected extractMethods(\n formDefinition: FormDefinition,\n controlId: string,\n ): Map<string, UseMethodDefinition> {\n const map = getMetadata<Map<string, Map<string, UseMethodDefinition>>>(\n RXAP_USE_METHOD,\n Object.getPrototypeOf(formDefinition),\n );\n\n if (!map) {\n console.log(map);\n throw new Error(\n 'Could not extract the use remote method map from the form definition instance',\n );\n }\n\n if (!map.has(controlId)) {\n throw new Error(\n 'A use remote method definition does not exists in the form definition metadata',\n );\n }\n\n return map.get(controlId)!;\n }\n\n}\n","import { Injector } from '@angular/core';\nimport { FormDefinition } from '@rxap/forms';\nimport { Mixin } from '@rxap/mixin';\nimport { ApplyUseMethodAdapters } from './apply-use-method.adapters';\nimport { ExtractMethodsMixin } from './extract-methods.mixin';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface ExtractMethodMixin extends ExtractMethodsMixin {\n}\n\n@Mixin(ExtractMethodsMixin)\nexport class ExtractMethodMixin {\n\n protected injector!: Injector;\n\n extractMethod(\n formDefinition: FormDefinition,\n controlId: string,\n name: string,\n ) {\n const map = this.extractMethods(formDefinition, controlId);\n if (!map.has(name)) {\n throw new Error(`A method with the name '${ name }' is not attached to the control '${ controlId }' use the @UseMethod decorator to attach a method to the control`);\n }\n const {method: methodToken, config} = map.get(name)!;\n const method = this.injector.get(methodToken);\n return ApplyUseMethodAdapters(this.injector, method, config);\n }\n\n}\n","import { ProviderToken } from '@angular/core';\nimport { RxapFormControl } from '@rxap/forms';\nimport { Mixin } from '@rxap/mixin';\nimport { Method } from '@rxap/pattern';\nimport { ControlOptions } from '@rxap/utilities';\nimport { ExtractControlMixin } from './extract-control.mixin';\nimport { ExtractFormDefinitionMixin } from './extract-form-definition.mixin';\nimport { ExtractMethodMixin } from './extract-method.mixin';\nimport {\n UseMethod,\n UseMethodConfig,\n} from './extract-methods.mixin';\n\nexport const OPTIONS_METHOD_NAME = 'options';\n\nexport function UseOptionsMethod(method: ProviderToken<Method<ControlOptions>>, config?: UseMethodConfig) {\n return function (target: any, propertyKey: string) {\n UseMethod(method, OPTIONS_METHOD_NAME, config)(target, propertyKey);\n };\n}\n\nexport interface ExtractOptionsMethodMixin extends ExtractFormDefinitionMixin, ExtractMethodMixin,\n ExtractControlMixin {\n}\n\n@Mixin(ExtractFormDefinitionMixin, ExtractMethodMixin, ExtractControlMixin)\nexport class ExtractOptionsMethodMixin {\n\n protected extractOptionsMethod(\n control: RxapFormControl = this.extractControl(),\n formDefinition = this.extractFormDefinition(control),\n ) {\n return this.extractMethod(formDefinition, control.controlId, OPTIONS_METHOD_NAME);\n }\n\n}\n","import { ProviderToken } from '@angular/core';\nimport { RxapFormControl } from '@rxap/forms';\nimport { Mixin } from '@rxap/mixin';\nimport { MethodWithParameters } from '@rxap/pattern';\nimport { ControlOption } from '@rxap/utilities';\nimport { ExtractControlMixin } from './extract-control.mixin';\nimport { ExtractFormDefinitionMixin } from './extract-form-definition.mixin';\nimport { ExtractMethodMixin } from './extract-method.mixin';\nimport {\n UseMethod,\n UseMethodConfig,\n} from './extract-methods.mixin';\n\nexport const RESOLVE_METHOD_NAME = 'resolve';\n\nexport function UseResolveMethod<Value = unknown>(\n method: ProviderToken<MethodWithParameters<ControlOption, Value>>,\n): any;\nexport function UseResolveMethod<Value = unknown>(\n method: ProviderToken<MethodWithParameters>,\n config: UseMethodConfig<ControlOption, Value>,\n): any;\nexport function UseResolveMethod<Value = unknown>(\n method: ProviderToken<MethodWithParameters<ControlOption, Value>>,\n config?: UseMethodConfig,\n) {\n return function (target: any, propertyKey: string) {\n UseMethod(method, RESOLVE_METHOD_NAME, config)(target, propertyKey);\n };\n}\n\nexport interface ExtractResolveMethodMixin extends ExtractFormDefinitionMixin, ExtractMethodMixin,\n ExtractControlMixin {\n}\n\n@Mixin(ExtractFormDefinitionMixin, ExtractMethodMixin, ExtractControlMixin)\nexport class ExtractResolveMethodMixin {\n\n protected extractResolveMethod(\n control: RxapFormControl = this.extractControl(),\n formDefinition = this.extractFormDefinition(control),\n ) {\n return this.extractMethod(formDefinition, control.controlId, RESOLVE_METHOD_NAME);\n }\n\n}\n","import { RxapFormControl } from '@rxap/forms';\nimport { Mixin } from '@rxap/mixin';\nimport { ExtractControlMixin } from './extract-control.mixin';\nimport { ExtractFormDefinitionMixin } from './extract-form-definition.mixin';\nimport { ExtractFunctionMixin } from './extract-function.mixin';\nimport {\n UseFunction,\n UseFunctionConfig,\n UseFunctionType,\n} from './extract-functions.mixin';\nimport { UseMethodConfig } from './extract-methods.mixin';\n\nexport const TO_DISPLAY_FUNCTION_NAME = 'to-display';\n\nexport function UseToDisplayFunction(\n fnc: UseFunctionType<[any], string>,\n): any;\nexport function UseToDisplayFunction(\n fnc: UseFunctionType<any[], any>,\n config: UseFunctionConfig<string, any[], any, [any]>,\n): any;\nexport function UseToDisplayFunction(\n fnc: UseFunctionType<[any], string>,\n config?: UseMethodConfig,\n) {\n return function (target: any, propertyKey: string) {\n UseFunction(fnc, TO_DISPLAY_FUNCTION_NAME, config)(target, propertyKey);\n };\n}\n\nexport interface ExtractToDisplayFunctionMixin extends ExtractFormDefinitionMixin, ExtractFunctionMixin,\n ExtractControlMixin {\n}\n\n@Mixin(ExtractFormDefinitionMixin, ExtractFunctionMixin, ExtractControlMixin)\nexport class ExtractToDisplayFunctionMixin {\n\n protected extractToDisplayFunction(\n defaultFunction: UseFunctionType<[any], string> | null = null,\n control: RxapFormControl = this.extractControl(),\n formDefinition = this.extractFormDefinition(control),\n ): UseFunctionType<[any], string> {\n return this.extractFunction(defaultFunction, formDefinition, control.controlId, TO_DISPLAY_FUNCTION_NAME);\n }\n\n}\n","import {\n AfterViewInit,\n ChangeDetectorRef,\n Directive,\n OnDestroy,\n SkipSelf,\n TemplateRef,\n ViewContainerRef,\n} from '@angular/core';\nimport {\n ControlContainer,\n UntypedFormArray,\n UntypedFormGroup,\n} from '@angular/forms';\nimport { RxapFormArray } from '@rxap/forms';\nimport {\n debounceTime,\n distinctUntilChanged,\n map,\n pairwise,\n startWith,\n Subscription,\n tap,\n} from 'rxjs';\n\nexport interface ForFormArrayItemsDirectiveContext {\n $implicit: UntypedFormGroup;\n index: number;\n last: boolean;\n first: boolean;\n even: boolean;\n odd: boolean;\n array: UntypedFormArray;\n}\n\n// TODO : move to rxap packages\n@Directive({\n selector: '[rxapForFormArrayItem]',\n standalone: true,\n})\nexport class ForFormArrayItemsDirective implements AfterViewInit, OnDestroy {\n\n private _formArrayValueSubscription?: Subscription;\n\n private formArray!: RxapFormArray;\n\n constructor(\n @SkipSelf() private readonly container: ControlContainer,\n private readonly template: TemplateRef<ForFormArrayItemsDirectiveContext>,\n private readonly viewContainerRef: ViewContainerRef,\n private readonly cdr: ChangeDetectorRef,\n ) {\n }\n\n ngAfterViewInit() {\n if (this.container.control instanceof RxapFormArray) {\n this.formArray = this.container.control;\n this.container.control.value$.pipe(\n debounceTime(100),\n map(value => value.length),\n distinctUntilChanged(),\n startWith(0),\n pairwise(),\n tap(([ a, b ]) => {\n if (a !== b) {\n this.render(b);\n }\n }),\n ).subscribe();\n } else {\n throw new Error('The control container is not an instance of RxapFormArray');\n }\n }\n\n ngOnDestroy() {\n this._formArrayValueSubscription?.unsubscribe();\n }\n\n private render(length: number) {\n this.viewContainerRef.clear();\n for (let index = 0; index < length; index++) {\n const group = this.formArray.at(index);\n if (group instanceof UntypedFormGroup) {\n this.viewContainerRef.createEmbeddedView(\n this.template,\n {\n $implicit: group,\n index,\n first: index === 0,\n last: index === length - 1,\n even: index % 2 === 0,\n odd: index % 2 !== 0,\n array: this.formArray,\n },\n );\n } else {\n throw new Error('rxapForFormArrayItem only support FormArray with FormGroup as items');\n }\n }\n this.cdr.detectChanges();\n }\n\n}\n","import {\n AfterViewInit,\n Directive,\n HostBinding,\n HostListener,\n OnDestroy,\n Optional,\n SkipSelf,\n} from '@angular/core';\nimport { ControlContainer } from '@angular/forms';\nimport { MatButton } from '@angular/material/button';\nimport { RxapFormArray } from '@rxap/forms';\nimport {\n Subscription,\n tap,\n} from 'rxjs';\n\n// TODO : move to rxap packages\n@Directive({\n selector: '[rxapFormArrayItemAddButton]',\n standalone: true,\n})\nexport class FormArrayAddItemButtonDirective implements AfterViewInit, OnDestroy {\n\n @HostBinding('type')\n type = 'button';\n protected formArray!: RxapFormArray;\n private _controlDisabledSubscription?: Subscription;\n\n constructor(\n @Optional() @SkipSelf() protected readonly parent: ControlContainer,\n @Optional() protected readonly matButton: MatButton,\n ) {\n }\n\n @HostBinding('disabled')\n get disabled() {\n return this.isDisabled;\n }\n\n protected get isDisabled(): boolean {\n return !!this.formArray?.disabled;\n }\n\n ngAfterViewInit() {\n if (this.parent.control instanceof RxapFormArray) {\n this.formArray = this.parent.control;\n }\n if (this.matButton) {\n this._controlDisabledSubscription = this.formArray.disabled$.pipe(\n tap(isDisabled => this.matButton.disabled = isDisabled),\n ).subscribe();\n }\n }\n\n ngOnDestroy() {\n this._controlDisabledSubscription?.unsubscribe();\n }\n\n @HostListener('click')\n protected onClick() {\n this.formArray.insertAt();\n }\n\n}\n","import {\n AfterViewInit,\n Directive,\n ElementRef,\n HostBinding,\n OnDestroy,\n Optional,\n Renderer2,\n SkipSelf,\n} from '@angular/core';\nimport {\n ControlContainer,\n UntypedFormArray,\n} from '@angular/forms';\nimport { MatButton } from '@angular/material/button';\nimport {\n RxapFormArray,\n RxapFormControl,\n RxapFormGroup,\n} from '@rxap/forms';\nimport {\n Subscription,\n tap,\n} from 'rxjs';\n\n// TODO : move to rxap packages\n@Directive()\nexport abstract class FormArrayItemButton implements AfterViewInit, OnDestroy {\n\n @HostBinding('type')\n type = 'button';\n protected formGroup!: RxapFormGroup<{ deleted: boolean }>;\n protected formArray!: RxapFormArray;\n protected deletedControl!: RxapFormControl<boolean>;\n private _controlDisabledSubscription?: Subscription;\n private _deletedControlValueSubscription?: Subscription;\n\n constructor(\n @SkipSelf() protected readonly parent: ControlContainer,\n @Optional() protected readonly matButton: MatButton,\n protected readonly renderer: Renderer2,\n protected readonly elementRef: ElementRef,\n ) {\n }\n\n @HostBinding('disabled')\n get disabled() {\n return this.isDisabled;\n }\n\n get isDeleted(): boolean {\n return this.deletedControl.value;\n }\n\n get index(): number {\n return this.formArray.controls.findIndex(control => control === this.formGroup);\n }\n\n protected get isDisabled(): boolean {\n return !!this.formGroup?.parent?.disabled;\n }\n\n ngAfterViewInit() {\n if (this.parent.control instanceof RxapFormGroup) {\n this.formGroup = this.parent.control;\n if (this.formGroup.controls.deleted) {\n if (this.formGroup.controls.deleted instanceof RxapFormControl) {\n this.deletedControl = this.formGroup.controls.deleted;\n } else {\n throw new Error(`The parent FormGroup instance does have a 'deleted' control, but it is not a RxapFormControl instance`);\n }\n } else {\n this.deletedControl = new RxapFormControl(false, { controlId: 'deleted' });\n this.formGroup.addControl('deleted', this.deletedControl);\n }\n if (this.formGroup.parent instanceof RxapFormArray) {\n this.formArray = this.formGroup.parent;\n } else {\n throw new Error(`The parent of the FormGroup is not a RxapFormArray instance`);\n }\n } else {\n throw new Error(`The parent is not a form group instance`);\n }\n if (this.matButton) {\n this._controlDisabledSubscription = this.formGroup.disabled$.pipe(\n tap(isDisabled => this.matButton.disabled = isDisabled),\n ).subscribe();\n }\n this.deletedControl.value$.pipe(\n tap(() => this.updateDisplayStyle()),\n ).subscribe();\n }\n\n ngOnDestroy() {\n this._controlDisabledSubscription?.unsubscribe();\n this._deletedControlValueSubscription?.unsubscribe();\n }\n\n protected abstract onClick(): void;\n\n protected abstract updateDisplayStyle(): void;\n\n}\n","import {\n AfterViewInit,\n Directive,\n HostListener,\n Input,\n OnDestroy,\n} from '@angular/core';\nimport { RxapFormGroup } from '@rxap/forms';\nimport { FormArrayItemButton } from './form-array-item-button';\n\n// TODO : move to rxap packages\n@Directive({\n selector: 'button[rxapFormArrayItemRemoveButton]',\n standalone: true,\n})\nexport class FormArrayItemRemoveButtonDirective extends FormArrayItemButton implements AfterViewInit, OnDestroy {\n\n /**\n * A function that returns if the control should be temporarily deleted.\n * true - in the given form group the deleted control is set to true\n * false - the form group is removed from the (parent) form array\n */\n @Input()\n public shouldTemporarilyDeleted: (formGroup: RxapFormGroup) => boolean = () => false;\n\n @HostListener('click')\n protected onClick() {\n const templateDelete = this.shouldTemporarilyDeleted(this.formGroup);\n if (templateDelete) {\n this.deletedControl.setValue(true);\n } else {\n this.formArray.removeAt(this.index);\n }\n }\n\n protected updateDisplayStyle() {\n if (this.isDeleted) {\n this.renderer.setStyle(this.elementRef.nativeElement, 'display', 'none');\n } else {\n this.renderer.removeStyle(this.elementRef.nativeElement, 'display');\n }\n }\n\n}\n","import {\n AfterViewInit,\n Directive,\n HostListener,\n OnDestroy,\n} from '@angular/core';\nimport { FormArrayItemButton } from './form-array-item-button';\n\n// TODO : move to rxap packages\n@Directive({\n selector: 'button[rxapFormArrayItemRestoreButton]',\n standalone: true,\n})\nexport class FormArrayItemRestoreButtonDirective extends FormArrayItemButton implements AfterViewInit, OnDestroy {\n\n @HostListener('click')\n override onClick() {\n this.formGroup.controls.deleted.setValue(false);\n }\n\n override updateDisplayStyle() {\n if (this.isDeleted) {\n this.renderer.removeStyle(this.elementRef.nativeElement, 'display');\n } else {\n this.renderer.setStyle(this.elementRef.nativeElement, 'display', 'none');\n }\n }\n\n}\n","import {\n AfterViewInit,\n Directive,\n OnDestroy,\n Optional,\n} from '@angular/core';\nimport {\n ControlContainer,\n UntypedFormArray,\n} from '@angular/forms';\nimport {\n RxapFormControl,\n RxapFormGroup,\n} from '@rxap/forms';\nimport {\n Subscription,\n tap,\n} from 'rxjs';\n\n// TODO : move to rxap packages\n@Directive({\n selector: '[rxapFormArrayRemovable]',\n standalone: true,\n})\nexport class FormArrayRemovableDirective implements AfterViewInit, OnDestroy {\n\n protected formGroup!: RxapFormGroup<{ deleted: boolean }>;\n\n protected deletedControl!: RxapFormControl<boolean>;\n private _deletedControlValueSubscription?: Subscription;\n\n constructor(@Optional() protected readonly parent: ControlContainer) {\n }\n\n get isDeleted(): boolean {\n return this.deletedControl.value;\n }\n\n protected get isDisabled(): boolean {\n return !!this.formGroup?.parent?.disabled;\n }\n\n ngAfterViewInit() {\n if (this.parent.control instanceof RxapFormGroup) {\n this.formGroup = this.parent.control;\n if (this.formGroup.controls.deleted) {\n if (this.formGroup.controls.deleted instanceof RxapFormControl) {\n this.deletedControl = this.formGroup.controls.deleted;\n } else {\n throw new Error(`The parent FormGroup instance does have a 'deleted' control, but it is not a RxapFormControl instance`);\n }\n } else {\n this.deletedControl = new RxapFormControl(false, { controlId: 'deleted' });\n this.formGroup.addControl('deleted', this.deletedControl);\n }\n if (!(this.formGroup.parent instanceof UntypedFormArray)) {\n throw new Error(`The parent of the FormGroup is not a FormArray instance`);\n }\n } else {\n throw new Error(`The parent is not a form group instance`);\n }\n this._deletedControlValueSubscription = this.deletedControl.value$.pipe(\n tap((isDeleted) => {\n for (const [ name, control ] of Object.entries(this.formGroup.controls)) {\n if (name !== 'deleted') {\n if (isDeleted) {\n control.disable({ onlySelf: true });\n } else if (!this.isDisabled) {\n control.enable({ onlySelf: true });\n }\n }\n }\n }),\n ).subscribe();\n }\n\n ngOnDestroy() {\n this._deletedControlValueSubscription?.unsubscribe();\n }\n\n}\n\n\n","import {\n AfterViewInit,\n ChangeDetectorRef,\n Directive,\n inject,\n InjectFlags,\n INJECTOR,\n Injector,\n Input,\n OnChanges,\n SimpleChanges,\n TemplateRef,\n ViewContainerRef,\n} from '@angular/core';\nimport {\n AbstractControlDirective,\n NgControl,\n} from '@angular/forms';\nimport { MatFormField } from '@angular/material/form-field';\nimport { RxapFormControl } from '@rxap/forms';\nimport { Mixin } from '@rxap/mixin';\nimport { Method } from '@rxap/pattern';\nimport {\n ControlOption,\n ControlOptions,\n} from '@rxap/utilities';\nimport { ExtractOptionsMethodMixin } from '../mixins/extract-options-method.mixin';\n\n\nexport interface OptionsFromMethodTemplateContext {\n $implicit: ControlOption;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface OptionsFromMethodDirectiveSettings {\n}\n\n// eslient-disable-next-line @typescript-eslint/no-empty-interface\nexport interface OptionsFromMethodDirective<Value = any, Parameters = any>\n extends AfterViewInit, OnChanges, ExtractOptionsMethodMixin {\n}\n\n@Mixin(ExtractOptionsMethodMixin)\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: '[rxapOptionsFromMethod]',\n standalone: true,\n})\nexport class OptionsFromMethodDirective<Value = any, Parameters = any> implements AfterViewInit, OnChanges {\n\n static ngTemplateContextGuard(\n dir: OptionsFromMethodDirective,\n ctx: any,\n ): ctx is OptionsFromMethodTemplateContext {\n return true;\n }\n\n @Input('rxapOptionsFromMethodParameters')\n public parameters?: Parameters;\n\n @Input('rxapOptionsFromMethodResetOnChange')\n public resetOnChange?: Value;\n\n public options: ControlOptions | null = null;\n // eslint-disable-next-line @angular-eslint/no-input-rename\n @Input('rxapOptionsFromMethodCall')\n public method!: Method<ControlOptions, Parameters>;\n protected ngControl: NgControl | AbstractControlDirective | null = null;\n protected matFormField: MatFormField | null = null;\n protected settings: OptionsFromMethodDirectiveSettings = {};\n protected readonly viewContainerRef: ViewContainerRef = inject(ViewContainerRef);\n protected readonly injector: Injector = inject(INJECTOR);\n protected readonly cdr: ChangeDetectorRef = inject(ChangeDetectorRef);\n private readonly template: TemplateRef<OptionsFromMethodTemplateContext> = inject(TemplateRef);\n\n public async ngAfterViewInit() {\n this.matFormField = this.injector.get(MatFormField, null);\n this.ngControl = this.matFormField?._control.ngControl ?? this.injector.get(NgControl, null);\n this.control = (this.ngControl?.control as RxapFormControl) ?? undefined;\n this.method ??= this.extractOptionsMethod();\n // ensure that the options are loaded. It is possible that the ngOnChange is triggered before the ngAfterViewInit\n // then the options are not loaded.\n if (!this.options) {\n this.setOptions(await this.loadOptions(this.parameters));\n }\n }\n\n public async ngOnChanges(changes: SimpleChanges) {\n // only try to load the options if the method is defined\n // else the initial load will be triggered in the ngAfterViewInit\n if (!this.method) {\n console.debug('The method is not yet defined');\n return;\n }\n const parametersChanges = changes['parameters'];\n if (parametersChanges) {\n this.setOptions(await this.loadOptions(parametersChanges.currentValue));\n }\n }\n\n protected async loadOptions(parameters?: Parameters): Promise<ControlOptions | null> {\n return this.method.call(parameters);\n }\n\n protected renderTemplate() {\n\n if (!this.options) {\n throw new Error('The options are not yet loaded');\n }\n\n this.viewContainerRef.clear();\n\n for (const option of this.options) {\n this.viewContainerRef.createEmbeddedView(this.template, {$implicit: option});\n }\n\n if (this.resetOnChange !== undefined) {\n this.control?.reset(this.resetOnChange);\n }\n\n this.cdr.detectChanges();\n\n }\n\n protected setOptions(options: ControlOptions | null) {\n if (!options) {\n this.options = null;\n this.viewContainerRef.clear();\n } else {\n this.options = options.slice();\n this.renderTemplate();\n }\n }\n\n}\n\n\n","import {\n AfterViewInit,\n Directive,\n inject,\n Injectable,\n Injector,\n INJECTOR,\n Input,\n isDevMode,\n OnDestroy,\n ProviderToken,\n} from '@angular/core';\nimport { MatAutocomplete } from '@angular/material/autocomplete';\nimport { ControlOption, ControlOptions } from '@rxap/utilities';\nimport { distinctUntilChanged, Subscription, tap } from 'rxjs';\nimport { isUUID } from '@rxap/validator';\nimport { Method, MethodWithParameters } from '@rxap/pattern';\nimport { Mixin } from '@rxap/mixin';\nimport { NgControl } from '@angular/forms';\nimport { MatFormField } from '@angular/material/form-field';\nimport { isDefined } from '@rxap/rxjs';\nimport { ExtractControlMixin } from '../mixins/extract-control.mixin';\nimport { ExtractFormDefinitionMixin } from '../mixins/extract-form-definition.mixin';\nimport {\n ExtractIsValueFunctionMixin,\n UseIsValueFunction,\n} from '../mixins/extract-is-value-function.mixin';\nimport { ExtractMethodMixin } from '../mixins/extract-method.mixin';\nimport { UseMethodConfig } from '../mixins/extract-methods.mixin';\nimport { Use