import { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y'; import { ChangeDetectorRef, OnChanges, OnDestroy } from '@angular/core'; import { AbstractControl, ControlValueAccessor, FormArray, FormControlDirective, FormControlName, FormGroup, NgModel, ValidationErrors } from '@angular/forms'; import { Observable, Subject } from 'rxjs'; import { DirectiveSuperclass } from './directive-superclass'; import * as i0 from "@angular/core"; /** * Extend this when creating a form control to reduce some boilerplate. * * When you simply need to use the same control that you're binding to via ngModel or formControl * on the inside of your custom component, then simply bind the inside control to `ngControl.control`: * ```ts * @Component({ * selector: 'app-one-input', * template: ` * * `, * }) * export class OneInputComponent extends FormComponentSuperclass {} * ``` * * If you have some custom component logic that requires its own state management, * use viewModel as the internal state * ```ts * @Component({ * selector: 'app-counter', * template: ` * * `, * }) * export class CounterComponent extends FormComponentSuperclass { * viewModel = new FormControl(0); * * increment() { * this.viewModel.setValue(this.viewModel.value + 1); * } * } * ``` * * Example when you need to transform the value used outside of the component to the * structure representing internal viewModel: * ```ts * @Component({ * selector: 'app-local-date', * template: ` * * `, * }) * export class LocalDateComponent extends FormComponentSuperclass { * viewModel = new FormControl(); * * outerToInner(incomingValues$: Observable): Observable { * return incomingValues$.pipe( * map((date) => { * if (!date) { * return ''; // happens during initialization * } * return date.toISOString().substr(0, 16); * }) * ); * } * * innerToOuter(outgoingValues$: Observable): Observable { * return outgoingValues$.pipe( * map((inner) => { * if (!inner) { * return (null as unknown) as Date; * } * return new Date(inner + 'Z'); * }) * ); * } * } * ``` */ export declare abstract class FormComponentSuperclass extends DirectiveSuperclass implements ControlValueAccessor, OnChanges, OnDestroy { /** * A reference to the outer control. Use ngControl.control inside of the template * if you want to simply forward the outer control. */ ngControl: FormControlDirective | FormControlName | NgModel; /** * Tracks internal control value (view-model). */ protected viewModel?: AbstractControl | FormGroup<{ [K in keyof InnerType]: any; }> | FormArray; /** * Resolved viewModel. * * Since `viewModel` is set in the class that extends from this class, * the `this.viewModel` is undefined at the time the observable expression * is defined. That's why we use the trick of `of(null).pipe(map(() => ...))`. * This way `this.viewModel` is defined when observable is subscribed to. */ private viewModel$; private viewModelValueChanges$; /** * Stream of values that are either set on the outer control * or set via the value property */ private incomingValues$$; protected hostEl: HTMLElement; protected focusMonitor: FocusMonitor; protected changeDetectorRef: ChangeDetectorRef; protected focusMonitor$: Observable; /** * Built-in validator reference */ private validator; private disabled$$; disabled$: Observable; id: string; stateChanges: Subject; get value(): OuterType; set value(val: OuterType); private _value; get disabled(): boolean; set disabled(value: boolean | string); private _focused; get focused(): boolean; set focused(val: boolean); /** * Stream that takes all incoming values, optionally applies user-provided * transformation, and commits the value to the inner form control */ private outerToInner$; /** * Stream that listens to values as user types in the input, optionally applies * user-provided transformation, and emits the result to the outer form control */ private innerToOuter$; latestValue$: Observable; innerControlValues$: Observable; constructor(); ngOnChanges(changes: any): void; ngOnDestroy(): void; /** * Implement this method in the consuming component for built-in validation. * @param control The control being validated */ validate?(control: AbstractControl): ValidationErrors | null; writeValue(): void; registerOnChange(): void; registerOnTouched(): void; /** Call this to "commit" a control visit, traditionally done e.g. on blur. */ onTouched(): void; /** Called as angular propagates disabled changes to this `ControlValueAccessor`. You normally do not need to use it. */ setDisabledState(isDisabled: boolean): void; /** * Override this to modify a value coming from the outside to the format needed within this component. * Example: * ```ts * return values$.pipe(map(val => val.toString())); * ``` * @param values$ Stream of values set from the outside * @returns Stream of transformed values that conform to the type of inner control */ protected outerToInner: (values$: Observable) => Observable; /** * Override this to modify a value coming from within this component to the format expected on the outside. * Example: * ```ts * return values$.pipe(map(val => parseInt(val))); * ``` * @param values$ Stream of inner formControl.valueChanges * @returns Stream of transformed values that conform to the type of outer control */ protected innerToOuter: (values$: Observable) => Observable; /** * Call this to emit a new value when it changes. */ private emitOutgoingValue; /** * Sets the instance of this component as the valueAccessor. Since this is * done here, there's no need to do that on the component that extends this class. * https://github.com/angular/components/blob/master/guides/creating-a-custom-form-field-control.md#ngcontrol */ private provideValueAccessor; private setupValidator; private monitorFocus; /** * Syncs touched and dirty states between inner controls and the forwarded ngControl * @param innerControls controls that need to be synced */ private syncOuterAndInnerControls; static ɵfac: i0.ɵɵFactoryDeclaration, never>; static ɵdir: i0.ɵɵDirectiveDeclaration, never, never, { "disabled": "disabled"; }, {}, never, never, false, never>; }