UNPKG

@rytrox/form-signals

Version:

Simple Reimplementation of [Angular Forms](https://www.npmjs.com/package/@angular/forms) in Signals. Focused on simplicity, with full [Angular Material](https://www.npmjs.com/package/@angular/material) support.

1,060 lines (1,034 loc) 45.8 kB
import * as i0 from '@angular/core'; import { signal, isSignal, computed, input, inject, ElementRef, effect, HostListener, Directive, booleanAttribute, forwardRef, NgModule } from '@angular/core'; import { isFunction } from 'lodash'; import { CommonModule } from '@angular/common'; import { MatCheckbox } from '@angular/material/checkbox'; import { MatRadioGroup } from '@angular/material/radio'; import { MatSliderThumb, MatSliderRangeThumb } from '@angular/material/slider'; import { MatSlideToggle } from '@angular/material/slide-toggle'; import { MatSelect } from '@angular/material/select'; import { MatButtonToggleGroup } from '@angular/material/button-toggle'; import { MatDatepickerInput } from '@angular/material/datepicker'; import { Subscription } from 'rxjs'; const createAbstractForm = (getter) => { const form = getter; const _validators = signal([]); Object.defineProperty(form, "validators", { value: _validators, writable: false }); Object.defineProperty(form, "addValidators", { value: (...validators) => { const set = new Set(_validators()); validators.forEach(validator => set.add(validator)); _validators.set([...set]); } }); Object.defineProperty(form, "removeValidators", { value: (...validators) => { const set = new Set(_validators()); validators.forEach(validator => set.delete(validator)); _validators.set([...set]); } }); Object.defineProperty(form, "hasValidator", { value: (validator) => { const set = new Set(_validators()); return set.has(validator); } }); return form; }; const isFormControl = (val) => { return isSignal(val) && 'errors' in val && isSignal(val.errors) && 'validators' in val && isSignal(val.validators) && 'disabled' in val && isSignal(val.disabled); }; const isSimpleFormOptions = (val) => { return !!val && typeof val === 'object' && 'value' in val && (!('disabled' in val) || typeof val.disabled === 'boolean') && (!('validators' in val) || Array.isArray(val.validators)); }; function formControl(val) { if (isSimpleFormOptions(val)) { return createSimpleForm(val); } else { return createSimpleForm({ value: val, disabled: false, validators: [], }); } } const createSimpleForm = (options) => { const form = createAbstractForm(signal(options.value)); if (options.validators) { form.addValidators(...options.validators); } Object.defineProperty(form, 'errors', { value: computed(() => { const validators = form.validators(); const value = form(); const errors = [...validators].map(validator => validator(value)) .filter((error) => !!error); return errors.length > 0 ? errors.reduce((error, current) => Object.assign(error, current), {}) : null; }) }); Object.defineProperty(form, 'disabled', { value: signal(!!options.disabled) }); return form; }; const formArrayFactory = (fn) => { return val => { const controls = signal(val.map(element => fn(element))); const form = createAbstractForm(computed(() => calcValue$1(controls()))); reindexArray(form, controls()); Object.defineProperty(form, 'length', { get() { return controls().length; } }); Object.defineProperty(form, 'push', { value: (value) => { const control = fn(value); controls.update(c => [...c, control]); reindexArray(form, controls()); } }); Object.defineProperty(form, 'removeAt', { value: (index) => { controls.update(controls => controls.filter((_control, i) => i !== index)); reindexArray(form, controls()); } }); Object.defineProperty(form, 'pop', { value: () => { controls.update(c => { c.pop(); return [...c]; }); Object.defineProperty(form, controls().length, { value: undefined, configurable: true }); } }); Object.defineProperty(form, Symbol.iterator, { get() { return controls()[Symbol.iterator]; } }); Object.defineProperty(form, 'errors', { value: computed(() => { // construct Error object const groupErrors = calcGroupErrors$1(form(), form.validators()); const controlErrors = calcControlErrors$1(controls()); if (groupErrors === null && Object.keys(controlErrors).length === 0) { return null; } return { this: groupErrors, controls: controlErrors }; }) }); Object.defineProperty(form, 'set', { value: (array) => { const properties = Object.fromEntries(controls().map((_control, index) => { return [index, { value: undefined, configurable: true }]; })); controls.set(array.map(element => fn(element))); Object.assign(properties, Object.fromEntries(controls().map((control, index) => { return [index, { value: control, configurable: true }]; }))); Object.defineProperties(form, properties); } }); Object.defineProperty(form, 'update', { value: (fn) => { form.set(fn(form())); } }); Object.defineProperty(form, 'disable', { value: () => { controls().forEach(control => { if (isFormControl(control)) { control.disabled.set(true); } else if ('disable' in control && isFunction(control.disable)) { control.disable(); } }); } }); Object.defineProperty(form, 'enable', { value: () => { controls().forEach(control => { if (isFormControl(control)) { control.disabled.set(false); } else if ('enable' in control && isFunction(control.enable)) { control.enable(); } }); } }); Object.defineProperty(form, 'map', { value: (callbackFn) => { return controls().map(callbackFn); } }); Object.defineProperty(form, 'forEach', { value: (callbackFn) => { controls().forEach(callbackFn); } }); return form; }; }; const calcValue$1 = (controls) => { return controls.map(control => control()); }; const reindexArray = (form, controls) => { Object.defineProperties(form, Object.fromEntries(controls.map((control, index) => { return [index, { value: control, configurable: true }]; }))); }; const calcGroupErrors$1 = (value, validators) => { const errors = validators.map(validator => validator(value)) .filter((error) => !!error); if (errors.length === 0) { return null; } return errors.reduce((error, current) => Object.assign(error, current), {}); }; const calcControlErrors$1 = (controls) => { return controls.map(control => control.errors()); }; const forbiddenNames = [ 'addValidators', 'removeValidators', 'setControl', 'hasValidator', 'errors', 'validators', ]; const formGroupFactory = (fn) => { return (val) => { const controls = signal(fn(val)); const form = createAbstractForm(computed(() => calcValue(controls()))); // Register Controls Object.entries(controls()) .filter((arr) => !!arr[1]) .forEach(([k, v]) => { if (!forbiddenNames.includes(k)) { Object.defineProperty(form, k, { value: v, configurable: true }); } else { throw new Error(`It is not allowed to name a property "${k}" inside a FormGroup. Please rename it`); } }); Object.defineProperty(form, 'errors', { value: computed(() => { // construct Error object const groupErrors = calcGroupErrors(form(), form.validators()); const controlErrors = calcControlErrors(controls()); if (groupErrors === null && Object.keys(controlErrors).length === 0) { return null; } return { this: groupErrors, controls: controlErrors }; }) }); Object.defineProperty(form, 'set', { value: (val) => { Object.entries(controls()) .filter((arr) => !!arr[1]) .forEach(([key, control]) => { control.set(val[key]); }); } }); Object.defineProperty(form, 'update', { value: (fn) => { form.set(fn(form())); } }); Object.defineProperty(form, 'setControl', { value: (key, control) => { if (control) { controls.update(c => { const newControls = { ...c }; newControls[key] = control; return newControls; }); Object.defineProperty(form, key, { value: control, configurable: true }); } else { controls.update(c => { const newControls = { ...c }; delete newControls[key]; return newControls; }); Object.defineProperty(form, key, { value: undefined, configurable: true }); } } }); Object.defineProperty(form, 'disable', { value: () => { Object.values(controls()) .filter((control) => !!control) .forEach(control => { if (isFormControl(control)) { control.disabled.set(true); } else if ('disable' in control && isFunction(control.disable)) { control.disable(); } }); } }); Object.defineProperty(form, 'enable', { value: () => { Object.values(controls()) .filter((control) => !!control) .forEach(control => { if (isFormControl(control)) { control.disabled.set(false); } else if ('disable' in control && isFunction(control.disable)) { control.disable(); } }); } }); return form; }; }; const calcValue = (controls) => { return Object.fromEntries(Object.entries(controls) .filter((arr) => !!arr[1]) .map(([key, val]) => [key, val()])); }; const calcGroupErrors = (value, validators) => { const errors = validators.map(validator => validator(value)) .filter((error) => !!error); if (errors.length === 0) { return null; } return errors.reduce((error, current) => Object.assign(error, current), {}); }; const calcControlErrors = (controls) => { return Object.fromEntries(Object.entries(controls) .filter((arr) => !!arr[1]) .map(([key, val]) => [key, val.errors()]) .filter(([_key, val]) => !!val)); }; class AbstractFormDirective { updateValue(form, value) { form.set(value); } } class InputTextDirective extends AbstractFormDirective { form = input(); element = inject(ElementRef); constructor() { super(); // Update input when form value is updated effect(() => { const form = this.form(); if (form) { this.element.nativeElement.value = form(); this.element.nativeElement.disabled = form.disabled(); } }); } onInput() { const form = this.form(); if (form) { this.updateValue(form, this.element.nativeElement.value); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputTextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: InputTextDirective, isStandalone: false, selector: "textarea[form], input:not([matDatepicker]):not([matSliderThumb]):not([matSliderStartThumb]):not([matSliderEndThumb]):not([type=number]):not([type=checkbox]):not([type=date]):not([type=datetime-local]):not([type=time]):not([type=radio]):not([type=range]):not([type=file])[form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onInput()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputTextDirective, decorators: [{ type: Directive, args: [{ selector: 'textarea[form], input:not([matDatepicker]):not([matSliderThumb]):not([matSliderStartThumb]):not([matSliderEndThumb]):not([type=number]):not([type=checkbox]):not([type=date]):not([type=datetime-local]):not([type=time]):not([type=radio]):not([type=range]):not([type=file])[form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onInput: [{ type: HostListener, args: ['input'] }] } }); class InputNumberDirective extends AbstractFormDirective { form = input(); element = inject(ElementRef); constructor() { super(); // Update input when form value is updated effect(() => { const form = this.form(); if (form) { this.element.nativeElement.valueAsNumber = form(); this.element.nativeElement.disabled = form.disabled(); } }); } /** * Blocks incoming input that are not numbers * * @param event */ onKeyDown(event) { if (event.key.length === 1 && !/[-+.0-9]/.test(event.key)) { event.preventDefault(); } } onInput() { const form = this.form(); if (form) { this.updateValue(form, this.element.nativeElement.valueAsNumber); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputNumberDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: InputNumberDirective, isStandalone: false, selector: "input[type=number][form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown": "onKeyDown($event)", "input": "onInput()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputNumberDirective, decorators: [{ type: Directive, args: [{ selector: 'input[type=number][form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }], onInput: [{ type: HostListener, args: ['input'] }] } }); class MatCheckboxDirective extends AbstractFormDirective { form = input(); element = inject(MatCheckbox, { self: true }); constructor() { super(); // Update input when form value is updated effect(() => { const form = this.form(); if (form) { this.element.writeValue(form()); this.element.setDisabledState(form.disabled()); } }); } onValueChange() { const form = this.form(); if (form) { this.updateValue(form, this.element.checked); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatCheckboxDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: MatCheckboxDirective, isStandalone: false, selector: "mat-checkbox[form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onValueChange()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatCheckboxDirective, decorators: [{ type: Directive, args: [{ selector: 'mat-checkbox[form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onValueChange: [{ type: HostListener, args: ['input'] }] } }); class InputCheckboxDirective extends AbstractFormDirective { form = input(); element = inject(ElementRef); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.nativeElement.checked = form(); this.element.nativeElement.disabled = form.disabled(); } }); } onChange() { const form = this.form(); if (form) { this.updateValue(form, this.element.nativeElement.checked); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputCheckboxDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: InputCheckboxDirective, isStandalone: false, selector: "input[type=checkbox][form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onChange()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputCheckboxDirective, decorators: [{ type: Directive, args: [{ selector: 'input[type=checkbox][form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onChange: [{ type: HostListener, args: ['input'] }] } }); class InputDateDirective extends AbstractFormDirective { form = input(); element = inject(ElementRef); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.nativeElement.valueAsDate = form(); this.element.nativeElement.disabled = form.disabled(); } }); } onInput() { const form = this.form(); if (form) { super.updateValue(form, this.element.nativeElement.valueAsDate); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputDateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: InputDateDirective, isStandalone: false, selector: "input[type=date][form], input[type=datetime-local][form], input[type=time][form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onInput()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputDateDirective, decorators: [{ type: Directive, args: [{ selector: 'input[type=date][form], input[type=datetime-local][form], input[type=time][form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onInput: [{ type: HostListener, args: ['input'] }] } }); class InputRadioDirective extends AbstractFormDirective { form = input(); element = inject(ElementRef); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.nativeElement.checked = form() === this.element.nativeElement.value; this.element.nativeElement.disabled = form.disabled(); } }); } onClick() { const form = this.form(); if (form) { const checked = this.element.nativeElement.checked; if (checked) { this.updateValue(form, this.element.nativeElement.value); } } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputRadioDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: InputRadioDirective, isStandalone: false, selector: "input[type=radio][form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "change": "onClick()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputRadioDirective, decorators: [{ type: Directive, args: [{ selector: 'input[type=radio][form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onClick: [{ type: HostListener, args: ['change'] }] } }); class MatRadioGroupDirective extends AbstractFormDirective { form = input(); element = inject(MatRadioGroup); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.writeValue(form()); this.element.setDisabledState(form.disabled()); } }); } onValueChange(event) { const form = this.form(); if (form) { this.updateValue(form, event.value); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatRadioGroupDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: MatRadioGroupDirective, isStandalone: false, selector: "mat-radio-group[form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "change": "onValueChange($event)" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatRadioGroupDirective, decorators: [{ type: Directive, args: [{ selector: 'mat-radio-group[form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onValueChange: [{ type: HostListener, args: ['change', ['$event']] }] } }); class InputRangeDirective extends AbstractFormDirective { form = input(); element = inject(ElementRef); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.nativeElement.valueAsNumber = form(); this.element.nativeElement.disabled = form.disabled(); } }); } onInput() { const form = this.form(); if (form) { this.updateValue(form, this.element.nativeElement.valueAsNumber); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputRangeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: InputRangeDirective, isStandalone: false, selector: "input[type=range][form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onInput()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputRangeDirective, decorators: [{ type: Directive, args: [{ selector: 'input[type=range][form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onInput: [{ type: HostListener, args: ['input'] }] } }); class InputFileDirective extends AbstractFormDirective { multiple = input(false, { transform: booleanAttribute }); form = input(); element = inject(ElementRef); constructor() { super(); effect(() => { const form = this.form(); if (form) { const val = form(); if (val) { const list = new DataTransfer(); if (Array.isArray(val)) { val.forEach(item => list.items.add(item)); } else { list.items.add(val); } this.element.nativeElement.files = list.files; } else { this.element.nativeElement.files = null; } this.element.nativeElement.disabled = form.disabled(); } }); } onFileChange() { const form = this.form(); if (form) { if (this.element.nativeElement.files) { const file = this.element.nativeElement.files; if (this.isFileArrayForm(form)) { const arr = []; for (let i = 0; i < file.length; i++) { const item = file.item(i); if (item) { arr.push(item); } } form.set(arr); } else { form.set(file.item(0)); } } else { form.set(null); } } } isFileArrayForm(_val) { return this.multiple(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputFileDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: InputFileDirective, isStandalone: false, selector: "input[multiple][type=file][form], input[type=\"file\"][form]", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onFileChange()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: InputFileDirective, decorators: [{ type: Directive, args: [{ selector: 'input[multiple][type=file][form], input[type="file"][form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onFileChange: [{ type: HostListener, args: ['input'] }] } }); class SelectDirective extends AbstractFormDirective { form = input(); element = inject(ElementRef); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.nativeElement.value = form(); this.element.nativeElement.disabled = form.disabled(); } }); } onChange() { const form = this.form(); if (form) { this.updateValue(form, this.element.nativeElement.value); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: SelectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: SelectDirective, isStandalone: false, selector: "select[form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "change": "onChange()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: SelectDirective, decorators: [{ type: Directive, args: [{ selector: 'select[form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onChange: [{ type: HostListener, args: ['change'] }] } }); class MatSliderThumbDirective extends MatSliderThumb { form = input(); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.writeValue(form()); this.setDisabledState(form.disabled()); } }); } onInput() { const form = this.form(); if (form) { form.set(this.value); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatSliderThumbDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: MatSliderThumbDirective, isStandalone: false, selector: "input[matSliderThumb][form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onInput()" } }, providers: [ { provide: MatSliderThumb, useExisting: forwardRef(() => MatSliderThumbDirective), } ], usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatSliderThumbDirective, decorators: [{ type: Directive, args: [{ selector: 'input[matSliderThumb][form]', providers: [ { provide: MatSliderThumb, useExisting: forwardRef(() => MatSliderThumbDirective), } ], standalone: false }] }], ctorParameters: () => [], propDecorators: { onInput: [{ type: HostListener, args: ['input'] }] } }); class MatSlideToggleDirective extends AbstractFormDirective { form = input(); element = inject(MatSlideToggle); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.writeValue(form()); this.element.setDisabledState(form.disabled()); } }); } onChange() { const form = this.form(); if (form) { this.updateValue(form, this.element.checked); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatSlideToggleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: MatSlideToggleDirective, isStandalone: false, selector: "mat-slide-toggle[form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "change": "onChange()" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatSlideToggleDirective, decorators: [{ type: Directive, args: [{ selector: 'mat-slide-toggle[form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onChange: [{ type: HostListener, args: ['change'] }] } }); class MatSelectDirective extends AbstractFormDirective { form = input(); element = inject(MatSelect); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.writeValue(form()); this.element.setDisabledState(form.disabled()); } }); } onChange(event) { const form = this.form(); if (form) { if (this.isArrayForm(form)) { const arr = Array.isArray(event.value) ? event.value : [event.value]; form.set(arr); } else { form.set(event.value); } } } isArrayForm(_form) { return this.element.multiple; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatSelectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: MatSelectDirective, isStandalone: false, selector: "mat-select[form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "selectionChange": "onChange($event)" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatSelectDirective, decorators: [{ type: Directive, args: [{ selector: 'mat-select[form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onChange: [{ type: HostListener, args: ['selectionChange', ['$event']] }] } }); class MatButtonToggleGroupDirective extends AbstractFormDirective { form = input(); element = inject(MatButtonToggleGroup); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.element.writeValue(form()); this.element.setDisabledState(form.disabled()); } }); } onChange(event) { const form = this.form(); if (form) { form.set(event.value); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatButtonToggleGroupDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: MatButtonToggleGroupDirective, isStandalone: false, selector: "mat-button-toggle-group[form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "change": "onChange($event)" } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatButtonToggleGroupDirective, decorators: [{ type: Directive, args: [{ selector: 'mat-button-toggle-group[form]', standalone: false }] }], ctorParameters: () => [], propDecorators: { onChange: [{ type: HostListener, args: ['change', ['$event']] }] } }); class MatSliderRangeThumbDirective extends MatSliderRangeThumb { form = input(); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.writeValue(form()); this.setDisabledState(form.disabled()); } }); } onInput() { const form = this.form(); if (form) { form.set(this.value); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatSliderRangeThumbDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: MatSliderRangeThumbDirective, isStandalone: false, selector: "input[matSliderStartThumb][form], input[matSliderEndThumb][form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onInput()" } }, providers: [ { provide: MatSliderRangeThumb, useExisting: forwardRef(() => MatSliderRangeThumbDirective), } ], usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatSliderRangeThumbDirective, decorators: [{ type: Directive, args: [{ selector: 'input[matSliderStartThumb][form], input[matSliderEndThumb][form]', providers: [ { provide: MatSliderRangeThumb, useExisting: forwardRef(() => MatSliderRangeThumbDirective), } ], standalone: false }] }], ctorParameters: () => [], propDecorators: { onInput: [{ type: HostListener, args: ['input'] }] } }); class MatDatepickerDirective extends AbstractFormDirective { form = input(); datePicker = inject(MatDatepickerInput); subscription = new Subscription(); constructor() { super(); effect(() => { const form = this.form(); if (form) { this.datePicker.writeValue(form()); this.datePicker.setDisabledState(form.disabled()); } }); this.subscription.add(this.datePicker.dateChange.subscribe(date => { const form = this.form(); if (form) { this.updateValue(form, date.value); } })); } ngOnDestroy() { this.subscription.unsubscribe(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatDatepickerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: MatDatepickerDirective, isStandalone: false, selector: "input[matDatepicker][form]", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: MatDatepickerDirective, decorators: [{ type: Directive, args: [{ selector: 'input[matDatepicker][form]', standalone: false }] }], ctorParameters: () => [] }); class FormsModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FormsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: FormsModule, declarations: [InputCheckboxDirective, InputDateDirective, InputFileDirective, InputNumberDirective, InputRadioDirective, InputRangeDirective, InputTextDirective, SelectDirective, MatButtonToggleGroupDirective, MatCheckboxDirective, MatDatepickerDirective, MatRadioGroupDirective, MatSelectDirective, MatSlideToggleDirective, MatSliderRangeThumbDirective, MatSliderThumbDirective], imports: [CommonModule], exports: [InputCheckboxDirective, InputDateDirective, InputFileDirective, InputNumberDirective, InputRadioDirective, InputRangeDirective, InputTextDirective, SelectDirective, MatButtonToggleGroupDirective, MatCheckboxDirective, MatDatepickerDirective, MatRadioGroupDirective, MatSelectDirective, MatSlideToggleDirective, MatSliderRangeThumbDirective, MatSliderThumbDirective] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FormsModule, imports: [CommonModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FormsModule, decorators: [{ type: NgModule, args: [{ declarations: [ InputCheckboxDirective, InputDateDirective, InputFileDirective, InputNumberDirective, InputRadioDirective, InputRangeDirective, InputTextDirective, SelectDirective, MatButtonToggleGroupDirective, MatCheckboxDirective, MatDatepickerDirective, MatRadioGroupDirective, MatSelectDirective, MatSlideToggleDirective, MatSliderRangeThumbDirective, MatSliderThumbDirective ], imports: [ CommonModule, ], exports: [ InputCheckboxDirective, InputDateDirective, InputFileDirective, InputNumberDirective, InputRadioDirective, InputRangeDirective, InputTextDirective, SelectDirective, MatButtonToggleGroupDirective, MatCheckboxDirective, MatDatepickerDirective, MatRadioGroupDirective, MatSelectDirective, MatSlideToggleDirective, MatSliderRangeThumbDirective, MatSliderThumbDirective ] }] }] }); /* * Public API Surface of form-signals */ /** * Generated bundle index. Do not edit. */ export { AbstractFormDirective, FormsModule, InputCheckboxDirective, InputDateDirective, InputFileDirective, InputNumberDirective, InputRadioDirective, InputRangeDirective, InputTextDirective, MatButtonToggleGroupDirective, MatCheckboxDirective, MatDatepickerDirective, MatRadioGroupDirective, MatSelectDirective, MatSlideToggleDirective, MatSliderRangeThumbDirective, MatSliderThumbDirective, SelectDirective, formArrayFactory, formControl, formGroupFactory, isFormControl }; //# sourceMappingURL=rytrox-form-signals.mjs.map