import WUPBaseElement from "./baseElement"; import IBaseControl from "./controls/baseControl.i"; import WUPSpinElement from "./spinElement"; export declare const enum SubmitActions { /** Disable any action */ none = 0, /** Scroll to first error (if exists) and focus control */ goToError = 1, /** Validate until first error is found (otherwise validate all) */ validateUntiFirst = 2, /** Collect to model only changed values */ collectChanged = 4, /** Reset isDirty and assign $value to $initValue for controls (on success only) */ reset = 8, /** Lock the whole form during the pending state (set $isPending = true or provide `promise` to submitEvent.waitFor); * Otherwise user can submit several times in a short time; * If promise resolves during the short-time pending state won't be set, otherwise it takes at least 300ms via helper {@link promiseWait} */ lockOnPending = 16 } declare const tagName = "wup-form"; declare global { namespace WUP.Form { interface SubmitEvent> extends Event { /** Model collected from controls */ $model: Partial; /** Form related to submit event */ $relatedForm: WUPFormElement; /** Event that produced submit event */ $relatedEvent: MouseEvent | KeyboardEvent; /** Element that that produced submit event */ $submitter: HTMLElement | null; /** Point a promise as callback to allow form show pending state during the promise */ $waitFor?: Promise; } interface EventMap extends WUP.Base.EventMap { /** Fires before $submit is happened; can be prevented via e.preventDefault() */ $willSubmit: Omit, "$model">; /** Fires by user-submit when validation succesfull and model is collected */ $submit: SubmitEvent; } interface Defaults { /** Actions that enabled on submit event; You can point several like: `goToError | collectChanged` * @defaultValue goToError | validateUntiFirst | reset | lockOnPending */ submitActions: SubmitActions; /** Whether need to store data in localStorage to prevent losing till submitted; * @defaultValue false * @tutorial Troubleshooting * * It doesn't save values that are complex objects. So `wup-select.$options.items = [{text: "N1",value: {id:1,name:'Nik'} }]` is skipped * * Point string-value if default storage-key doesn't fit: based on `url+control.names` @see{@link WUPFormElement.storageKey} */ autoSave?: boolean | string; } interface Options extends Defaults { /** Focus first possible element when it's appended to layout */ autoFocus?: boolean; /** Disallow edit/copy value; adds attr [disabled] for styling */ disabled?: boolean; /** Disallow copy value; adds attr [readonly] for styling */ readOnly?: boolean; /** Enable/disable browser-autocomplete; if control has no autocomplete option then it's inherited from form * @defaultValue false */ autoComplete?: boolean; } interface Attributes extends Pick { } interface JSXProps extends WUP.Base.JSXProps, Attributes { /** Whether need to store data in localStorage to prevent losing till submitted; * @defaultValue false * @tutorial Troubleshooting * * It doesn't save values that are complex objects. So `wup-select.$options.items = [{text: "N1",value: {id:1,name:'Nik'} }]` is skipped * * Point string-value if default storage-key doesn't fit: based on `url+control.names` @see{@link WUPFormElement.storageKey} */ autoSave?: string; /** @deprecated SyntheticEvent is not supported. Use ref.addEventListener('$change') instead */ onChange?: never; /** @deprecated SyntheticEvent is not supported. Use ref.addEventListener('$willSubmit') instead */ onWillSubmit?: never; /** @deprecated SyntheticEvent is not supported. Use ref.addEventListener('$submit') instead */ onSubmit?: never; } } interface HTMLElementTagNameMap { [tagName]: WUPFormElement; } namespace JSX { interface IntrinsicElements { /** Wrapper of FormHTMLElement that collect values from controls * @see {@link WUPFormElement} */ [tagName]: WUP.Form.JSXProps; } } } /** Wrapper of FormHTMLElement that collect values from controls * @example * // init form * const form = document.createElement("wup-form"); * form.$options.autoComplete = false; * form.$initModel = { email: "test-me@google.com" }; * form.addEventListener("$submit", (e) => console.warn(e.$model) ); * form.$onSubmit = async (e)=>{ await postHere(e.$model); } // equal to form.addEventListener * // init control * const el = document.createElement("wup-text"); * el.$options.name = "email"; * el.$options.validations = { required: true, email: true }; * form.appendChild(el); * const btn = form.appendChild(document.createElement("button")); * btn.textContent = "Submit"; * btn.type = "submit"; * document.body.appendChild(form); * // or HTML * * * /> */ export default class WUPFormElement = any, TOptions extends WUP.Form.Options = WUP.Form.Options, Events extends WUP.Form.EventMap = WUP.Form.EventMap> extends WUPBaseElement { #private; /** Options that need to watch for changes; use gotOptionsChanged() */ static get observedOptions(): Array; static get observedAttributes(): Array>; static get $styleRoot(): string; static get $style(): string; /** Find form related to control,register and apply initModel if initValue undefined */ static $tryConnect(control: IBaseControl & HTMLElement): WUPFormElement | undefined; /** Map model to control-values */ static $modelToControls>(m: T | undefined, controls: IBaseControl[], prop: keyof Pick): void; /** Collect model from control-values */ static $modelFromControls(prevModel: Partial, controls: IBaseControl[], prop: keyof Pick, isOnlyChanged?: boolean): Partial; /** Default options - applied to every element. Change it to configure default behavior */ static $defaults: WUP.Form.Defaults; /** Dispatched on submit. Return promise to lock form and show spinner */ $onSubmit?: (ev: WUP.Form.SubmitEvent) => void | Promise; /** Dispatched on submit */ /** All controls related to form */ $controls: IBaseControl[]; /** Returns related to form controls with $options.name != null */ get $controlsAttached(): IBaseControl[]; _model?: Partial; /** Model related to every control inside (with $options.name); * @see {@link BaseControl.prototype.$value} */ get $model(): Partial; set $model(m: Partial); _initModel?: Partial; /** Default/init model related to every control inside; * @see {@link BaseControl.prototype.$initValue} */ get $initModel(): Partial | undefined; set $initModel(m: Partial | undefined); /** Pending state (spinner + lock form if SubmitActions.lockOnPending enabled) */ get $isPending(): boolean; set $isPending(v: boolean); /** Returns true if all nested controls (with name) are valid */ get $isValid(): boolean; /** Returns true if some of controls value is changed by user */ get $isChanged(): boolean; /** Called on every spin-render */ renderSpin(target: HTMLElement): WUPSpinElement; /** Change pending state */ protected changePending(v: boolean): void; /** Called on submit before validation */ protected gotSubmit(e: KeyboardEvent | MouseEvent, submitter: HTMLElement): void; protected gotChanges(propsChanged: Array> | null): void; protected gotOptionsChanged(e: WUP.Base.OptionEvent>): void; protected gotAttributeChanged(name: string, oldValue: string, newValue: string): void; protected gotReady(): void; protected connectedCallback(): void; /** Returns storage key based on url+control-names or `$options.autoSave` if `string` */ get storageKey(): string; /** Get & parse value from storage according to option `autoSave`, $model */ storageGet(): Partial | null; _preventStorageSave?: boolean; /** Save/remove model (only changes) to storage according to option `autoSave`, $model * @returns model saved to localStorage or Null if removed */ storageSave(model?: null | Record): Partial | null; protected disconnectedCallback(): void; } export {};