@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
494 lines (493 loc) • 19.8 kB
TypeScript
import { AfterViewInit, ChangeDetectorRef, DoCheck, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, SimpleChanges, TemplateRef } from '@angular/core';
import { FormControl, NgControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { Strings } from '../../../generated/strings';
import { BaseComponent } from '../../common/base.component';
import { ValidationAlert, ValidationAlerts, ValidationResult } from '../validation-alert/validation-alert';
import { FormFieldAggregatable } from './form-field-aggregator';
import { FormFieldContainer } from './form-field-container';
import { FormFieldOrientation } from './form-field-orientation';
import * as i0 from "@angular/core";
/**
* Base component class for form fields
* A circular reference would be created by injecting both ngModel
* and providing @see ControlValueAccessor and @see Validator implementations on the same component.
* Therefore, we have broken the FormField component into 3 parts.
* - The @see FormFieldValidatorDirective handles the implementation of @see Validator and @see NG_VALIDATORS
* - The @see FormFieldAccessorDirective handles the implementation of @see ControlValueAccessor and @see NG_VALUE_ACCESSOR
* - This @see FormFieldComponent is our glue that pulls it all together with labels and alerts and injects the NgControl instance safely.
*
* In order for this to work, all three components must use the same base selector @see FormFieldComponent.selector.
* This is enforced in the constructor of this component,
* However the directives are done by convention and will just crash if the injector cannot find them.
*
*/
/**
*
* @smeDoc {@label Form fields @id sme-form-fields-component}
*
* @overview
* @file {@filepath ./examples/overview.md}
*
* @example {@label Search with emphasized search button @id search-emphasis}
* @file {@filename component.ts @filepath ./examples/search-emphasize.component.ts}
* @file {@filename component.html @filepath ./examples/search-emphasize.component.html}
*
* @example {@label Search with hidden label @id search-hidden}
* @file {@filename component.ts @filepath ./examples/search-hidden-label.component.ts}
* @file {@filename component.html @filepath ./examples/search-hidden-label.component.html}
*
* @example {@label Search with required field @id search-required}
* @file {@filename component.ts @filepath ./examples/search-required.component.ts}
* @file {@filename component.html @filepath ./examples/search-required.component.html}
*
* @example {@label Calendar @id calendar}
* @file {@filename component.html @filepath ./examples/calendar.component.html}
*
* @example {@label Clock @id clock}
* @file {@filename component.ts @filepath ./examples/clock.component.ts}
* @file {@filename component.html @filepath ./examples/clock.component.html}
*
* @example {@label Datetime @id datetime}
* @file {@filename component.ts @filepath ./examples/datetime.component.ts}
* @file {@filename component.html @filepath ./examples/datetime.component.html}
*
* @example {@label Validation error @id validation-error}
* @file {@filename component.ts @filepath ./examples/validation-error.component.ts}
* @file {@filename component.html @filepath ./examples/validation-error.component.html}
*
* @example {@label Validation pending @id validation-pending}
* @file {@filename component.ts @filepath ./examples/validation-pending.component.ts}
* @file {@filename component.html @filepath ./examples/validation-pending.component.html}
*
* @example {@label Validation with custom markdown @id validation-markdown}
* @file {@filename component.ts @filepath ./examples/validation-markdown.component.ts}
* @file {@filename component.ts @filepath ./examples/validation-markdown.component.html}
*
* @example {@label Basic combobox @id combobox}
* @file {@filename component.ts @filepath ./examples/combobox.component.ts}
* @file {@filename component.html @filepath ./examples/combobox.component.html}
*
* @example {@label Combobox with search @id combobox-search}
* @file {@filename component.ts @filepath ./examples/combobox-search.component.ts}
* @file {@filename component.html @filepath ./examples/combobox-search.component.html}
*
* @example {@label Multiple select comboxbox @id combobox-multi}
* @file {@filename component.ts @filepath ./examples/combobox-multi.component.ts}
* @file {@filename component.html @filepath ./examples/combobox-multi.component.html}
*
* @example {@label Multiple select combobox with minwidth @id combobox-multi-minwidth}
* @file {@filename component.ts @filepath ./examples/combobox-multi-minwidth.component.ts}
* @file {@filename component.html @filepath ./examples/combobox-multi-minwidth.component.html}
*
* @example {@label Multiple select combobox with custom tooltip @id custom-tooltip}
* @file {@filename component.ts @filepath ./examples/custom-tooltip.component.ts}
* @file {@filename component.html @filepath ./examples/custom-tooltip.component.html}
*/
export declare abstract class FormFieldComponent<TStrings, TModel> extends BaseComponent<TStrings> implements OnInit, OnDestroy, DoCheck, OnChanges, AfterViewInit, FormFieldAggregatable {
/**
* The selector that all form fields must use in order to work properly with
* @see FormFieldAccessorDirective and @see FormFieldValidatorDirective
*/
static readonly selector = "sme-form-field";
/**
* The type of field that we are dealing with. This is a required property
*/
type: string;
/**
* Indicates that the header of this form field should be hidden from view (but not necessarily from aria)
* Not supported on all form fields
*/
hideHeader: boolean;
/**
* Indicates if to maintain the space left after hidding header
*/
hideHeaderSpace: boolean;
/**
* Indicates that this requires a value
*/
required: boolean;
/**
* Indicates that this requires a value
*/
autofocus: boolean;
/**
* The placeholder for the internal form control
*/
placeholder: string;
/**
* The label that identifies this control to the user
*/
label: string;
/**
* It determines whether to render the label in vertical middle
*/
verticalMiddleLabel: boolean;
/**
* The template ref of a subform of this component. The way this template ref is used varies form field to field
*/
subFormTemplate: TemplateRef<any>;
/**
* The description of this field; A description for the user of the meaning and purpose of this field
*/
get description(): string;
set description(value: string);
compact: boolean;
minimal: boolean;
/**
* It indicates whether the form field is readonly.
*/
readonly: boolean;
/**
* The instructions of this control; A built in description for the user of how this control works.
* This should be provided by the control and applies to all instances of the control, but can be overridden as an attribute.
*/
get instructions(): string;
set instructions(value: string);
/**
* If provided, renders a custom tooltip for this field
*/
tooltipTemplate: TemplateRef<any>;
/**
* The tooltip. If not provided, details property will be used
*/
tooltip: string;
/**
* Provides binding context for the tooltip
*/
tooltipContext: any;
/**
* Indicates that this form control is truly disabled
* This will be true if the accessor (model), input, or ancestor is disabled
* Its value is set only on DoCheck.
*/
get disabled(): boolean;
/**
* It indicates whether the form field is pending validation
*/
get pending(): boolean;
get dirty(): boolean;
get touched(): boolean;
get loadingOrDisabled(): boolean;
/**
* Placeholder for the bound input of the disabled property
*/
disabledInput: boolean;
/**
* Indicates whether the form field is loading
*/
loading: boolean;
/**
* The message to show while loading
*/
loadingMessage: string;
/**
* The message to show while pending
*/
pendingMessage: string;
/**
* Overrides the default dataUtaId if passed in
*/
utaId: string;
/**
* The form field's UTA id getter.
* The ID is based on the form field name that's set on the ngModel.
*/
get dataUtaId(): string;
/**
* Placeholder for the combined disabled state
*/
private get internalDisabled();
/**
* Placeholder for the ancestor disabled state
*/
private ancestorDisabled;
/**
* Indicates that the ancestor disabled state is being reflected in the current model
*/
private expectDisabledByAncestor;
/**
* Indicates that the input disabled state is being reflected in the current model
*/
private expectDisabledByInput;
/**
* Placeholder for the ancestor disabled state
*/
private disabledByModel;
protected get fieldName(): string;
/**
* The value of this field.
* safe wrapper around this.accessor.value
*/
get value(): TModel;
set value(value: TModel);
get showInfoBubble(): boolean;
get resolvedTooltipTemplate(): TemplateRef<any>;
get resolvedTitle(): string;
/**
* Aggregate property for the details for of this control (description merged with instructions)
*/
details: string;
/**
* The current alert to display for this control
*/
alert: ValidationAlert;
/**
* The current non-error alerts to display for this control
*/
private nonErrorAlerts;
/**
* The current non-error async alerts to display for this control
*/
private nonErrorAsyncAlerts;
/**
* Indicates that immediate validation is enabled
*/
immediateValidation: boolean;
change: EventEmitter<TModel>;
/**
* Indicates the default value for immediateValidation.
* This is meant to be overridden by derived classes
*/
protected get defaultImmediateValidation(): boolean;
errorAlertBorder: Boolean;
/**
* Indicates if the form field should layout horizontally
*/
get isHorizontalLayout(): boolean;
/**
* Indicates if the form field should layout vertically
*/
get isVerticalLayout(): boolean;
/**
* Indicates the desired orientation of the form field.
* When provided, the form field will no longer dynamically chang its orientation.
*/
orientation: FormFieldOrientation.Bindable;
/**
* Placeholder for the calculated orientation
*/
calculatedOrientation: FormFieldOrientation.Bindable;
/**
* Injected @see NgControl instance bound to this component.
*/
ngModel: NgControl;
/**
* Injected @see FormFieldAccessorDirective instance bound to this component.
*/
private accessor;
/**
* Injected @see FormFieldValidatorDirective instance bound to this component.
*/
private validator;
/**
* Injected @see FormFieldValidatorDirective instance bound to this component.
*/
private asyncValidator;
/**
* Injected @see FormFieldAggregator parent instance bound to this component.
*/
private aggregator;
/**
* Injected @see Layout parent instance bound to this component.
*/
private layout;
/**
* Injected @see ChangeDetectorRef instance bound to this component.
*/
protected changeDetectorRef: ChangeDetectorRef;
formFieldContainer: FormFieldContainer;
/**
* Getter for the available width for subfields to consume
*/
protected get subFieldLayoutWidth(): number;
/**
* Internal placeholder for the description of this field
*/
private internalDescription;
/**
* Internal placeholder for the instructions of this control
*/
private internalInstructions;
/**
* Holds the initial value of the field
*/
private initialValue;
/**
* Indicates that the initial value has been tracked
*/
private valueInitialized;
/**
* Gets the width to base layout decisions on
*/
private get layoutWidth();
/**
* Gets the layout width as detected on the last DoCheck()
*/
private previouslyCheckedLayoutWidth;
/**
* Constructs a new instance of @see FormFieldComponent
* @param injector the angular injection service for the base classes @SmeInjectableBase Annotation.
*/
constructor(injector: Injector);
/**
* Implementation of angular OnInit interface
*/
ngOnInit(): void;
/**
* Implementation of angular DoCheck interface
*/
ngDoCheck(): void;
/**
* synchronizes the expected disabled state with the actual state of the model
*/
private synchronizeDisabledState;
ngOnChanges(changes: SimpleChanges): void;
ngAfterViewInit(): void;
/**
* Implementation of angular OnDestroy interface
* derived classes are always expected to call super.ngOnDestroy() when overriding
*/
ngOnDestroy(): void;
/**
* On layout changed event handler, occurs every time the layout has been changed.
*/
protected onLayoutChanged(): void;
/**
* Occurs every time the orientation has been changed.
*/
protected onOrientationChanged(): void;
/**
* Occurs every time the layout has been changed.
*/
private yieldOnLayoutChanged;
/**
* Occurs every time the layout has been changed.
*/
private yieldOnOrientationChanged;
/**
* Resets this field to its initial value
*/
reset(): void;
/**
* Clears the value of this field base on the initial values type.
*/
clear(): void;
/**
* Copies the fields value to the clipboard.
*/
copyToClipboard(): void;
/**
* Check whether the header should be displayed.
*/
shouldDisplayHeader(): boolean;
/**
* Gets a value indicating if this form field is valid
*/
isValid(): boolean;
/**
* Gets a value indicating if the form field is dirty.
*/
isDirty(): boolean;
/**
* Marks the form field as pristine.
*/
markAsPristine(): void;
/**
* Marks the form field as dirty.
*/
markAsDirty(): void;
/**
* Applies the focus to the current element
*/
focus(): void;
/**
* Occurs every time the control is disabled or enabled.
* @param disabled The new disabled state of the control
*/
protected ngModelDisabledChanged(disabled: boolean): void;
/**
* Determines the value to use when clearing the field based on the initial value type
* Derived fields may override this to change the clear value behavior
*/
protected getClearValue(): TModel;
/**
* Performs validation that is internal to this control
* @param c The form control attached to this instance
*/
protected validate(c: FormControl): ValidationAlerts;
/**
* Performs asynchronous validation that is internal to this control
* @param c The form control attached to this instance
*/
protected asyncValidate(c: FormControl): Observable<ValidationAlerts>;
/**
* Occurs any time value changed.
*/
protected updateDetails(): void;
/**
* Gets the initial host classes to be applied to this element
* When called in the @see BaseComponent super class initialization, These classes will be automatically assigned to the host element.
*/
protected getInitialHostClasses(): string[];
/**
* Occurs every time the value of the control changes, in the UI or programmatically.
* @param value the value of the form control
*/
protected onValueChanged(value: TModel): void;
/**
* Occurs every time the validation status of the control has been re-calculated.
* @param status the status object of the form control
*/
protected onStatusChanged(status: any): void;
/**
* Occurs every time there are alert changes from the validator directive
* @param alerts the alerts from the validator directive
*/
protected onAlert(alerts: ValidationAlerts): void;
/**
* Occurs every time there are alert changes from the validator directive
* @param alerts the alerts from the validator directive
*/
protected onAsyncAlert(alerts: ValidationAlerts): void;
/**
* Removes the error alerts from a ValidationAlert Objects
* errors will be surfaced in the this.ngModel.control.errors instead
* @param alerts the alerts to filter
*/
private removeErrorAlerts;
/**
* Updates the form field border to reflect error alerts
*/
private updateBorderState;
/**
* Updates the active alerts of this control
*/
protected updateAlerts(): void;
private addVisibleAlerts;
/**
* gets an alert object from a key and validation result
*/
protected getAlert(key: string, alert: ValidationResult): ValidationAlert;
/**
* Gets an alert object from known angular alert keys
*/
protected getKnownNgAlert(key: string, alert: any): ValidationAlert;
/**
* In some cases, we need a combined version of the label and description so that the screen read can read it appropriately.
* Common cases for this are when using role="group" or role="radioGroup" because they does not support aria-describedby
* we achieve the same effect by splitting the description and and label with a '.' (period)"
* TODO: verify how this localizes or find a better way.
*/
protected getMergedDescriptionLabel(): string;
static ɵfac: i0.ɵɵFactoryDeclaration<FormFieldComponent<any, any>, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<FormFieldComponent<any, any>, never, never, { "type": "type"; "hideHeader": "hideHeader"; "hideHeaderSpace": "hideHeaderSpace"; "required": "required"; "autofocus": "autofocus"; "placeholder": "placeholder"; "label": "label"; "verticalMiddleLabel": "verticalMiddleLabel"; "description": "description"; "compact": "compact"; "minimal": "minimal"; "readonly": "readonly"; "instructions": "instructions"; "tooltipTemplate": "tooltipTemplate"; "tooltip": "tooltip"; "tooltipContext": "tooltipContext"; "disabledInput": "disabled"; "loading": "loading"; "loadingMessage": "loadingMessage"; "pendingMessage": "pendingMessage"; "utaId": "utaId"; "immediateValidation": "immediateValidation"; "orientation": "orientation"; "formFieldContainer": "formFieldContainer"; }, { "change": "change"; }, ["subFormTemplate"], never, false, never>;
}
/**
* Internal base component for SME for fields. It simply removes the need to supply the string type parameter to FormFieldComponent
* This class is exported from this file, but not meant to be exported from index.ts bundles.
*/
export declare abstract class SmeInternalFormFieldComponent<TModel> extends FormFieldComponent<Strings, TModel> {
static ɵfac: i0.ɵɵFactoryDeclaration<SmeInternalFormFieldComponent<any>, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<SmeInternalFormFieldComponent<any>, never, never, {}, {}, never, never, false, never>;
}