Core form package

This commit is contained in:
Niels Lyngsø
2024-03-25 14:23:39 +01:00
parent 6786c9713d
commit eb2b7fd4dd
11 changed files with 121 additions and 5 deletions

View File

@@ -38,6 +38,7 @@
"./entity-bulk-action": "./dist-cms/packages/core/entity-bulk-action/index.js",
"./event": "./dist-cms/packages/core/event/index.js",
"./extension-registry": "./dist-cms/packages/core/extension-registry/index.js",
"./form": "./dist-cms/packages/core/form/index.js",
"./icon": "./dist-cms/packages/core/icon-registry/index.js",
"./id": "./dist-cms/packages/core/id/index.js",
"./language": "./dist-cms/packages/language/index.js",

View File

@@ -0,0 +1,22 @@
import { UmbFormContext } from '../context/form.context.js';
import { type PropertyValueMap, customElement, html } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
@customElement('umb-form')
export class UmbFormElement extends UmbLitElement {
readonly #context = new UmbFormContext(this);
protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
super.firstUpdated(_changedProperties);
this.#context.setFormElement(this.shadowRoot!.querySelector<HTMLFormElement>('form'));
}
render() {
return html`<uui-form>
<form>
<slot></slot>
</form>
</uui-form>`;
}
}

View File

@@ -0,0 +1,4 @@
import type { UmbFormContext } from './form.context.js';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export const UMB_FORM_CONTEXT = new UmbContextToken<UmbFormContext>('UmbFormContext');

View File

@@ -0,0 +1,81 @@
import { UMB_FORM_CONTEXT } from './form.context-token.js';
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbValidationManager } from '@umbraco-cms/backoffice/validation';
/**
* @description The Form Context is used to handle form submission and validation.
* @event submit - Fired when the form is submitted.
*/
export class UmbFormContext extends UmbContextBase<UmbFormContext> {
#formElement?: HTMLFormElement;
#validation: UmbValidationManager[] = [];
constructor(host: UmbControllerHost) {
super(host, UMB_FORM_CONTEXT);
}
/**
* Method to call in the implementation once the form element is available.
* @param element {HTMLFormElement | null} - The Form element to be used for this context.
*/
setFormElement(element: HTMLFormElement | null) {
if (this.#formElement === element) return;
if (this.#formElement) {
this.#formElement.removeEventListener('submit', this.onSubmit);
this.#formElement.removeEventListener('reset', this.onReset);
}
if (element) {
this.#formElement = element;
this.#formElement.addEventListener('submit', this.onSubmit);
this.#formElement.addEventListener('reset', this.onReset);
}
}
/**
* Define one or more validation managers to be used for this form.
* These will be called when the form is requested to be submitted.
* @param manager {UmbValidationManager} - A manager to be bound to this form.
*/
registerValidationManager(manager: UmbValidationManager) {
this.#validation.push(manager);
}
/**
* Call this method to submit the form
*/
requestSubmit() {
// We do not call requestSubmit here, as we want the form to submit, and then we will handle the validation as part of the submit event handling.
this.#formElement?.submit();
}
/**
* @description Triggered by the form, when it fires a submit event
*/
onSubmit = (event: SubmitEvent) => {
event?.preventDefault();
//this.dispatchEvent(new CustomEvent('submit-requested'));
// Check client validation:
const isClientValid = this.#formElement?.checkValidity();
// ask validation managers to validate the form.
const isValid = isClientValid ?? false;
if (!isValid) {
// Fire invalid..
return;
}
// Fire submit event...
this.dispatchEvent(new CustomEvent('submit'));
};
/**
* @description Triggered by the form, when it fires a reset event
*/
onReset = (event: Event) => {
// ask validation managers to reset.
};
}

View File

@@ -0,0 +1,2 @@
export * from './form.context.js';
export * from './form.context-token.js';

View File

@@ -0,0 +1 @@
export * from './context/index.js';

View File

@@ -1,3 +1,4 @@
export * from './events/index.js';
export * from './interfaces/index.js';
export * from './mixins/index.js';
export * from './context/index.js';

View File

@@ -0,0 +1 @@
export type * from './validation-manager.interface.js';

View File

@@ -0,0 +1,4 @@
export interface UmbValidationManager {
validate(): Promise<boolean>;
// reset?
}

View File

@@ -17,11 +17,9 @@ export class UmbEditableWorkspaceElement extends UmbLitElement {
}
render() {
return html`<uui-form>
<form>
<umb-router-slot .routes="${this._routes}"></umb-router-slot>
</form>
</uui-form>`;
return html`<umb-form>
<umb-router-slot .routes="${this._routes}"></umb-router-slot>
</umb-form>`;
}
}

View File

@@ -56,6 +56,7 @@
"@umbraco-cms/backoffice/entity-bulk-action": ["./src/packages/core/entity-bulk-action/index.ts"],
"@umbraco-cms/backoffice/event": ["./src/packages/core/event/index.ts"],
"@umbraco-cms/backoffice/extension-registry": ["./src/packages/core/extension-registry/index.ts"],
"@umbraco-cms/backoffice/form": ["./src/packages/core/form/index.ts"],
"@umbraco-cms/backoffice/icon": ["./src/packages/core/icon-registry/index.ts"],
"@umbraco-cms/backoffice/id": ["./src/packages/core/id/index.ts"],
"@umbraco-cms/backoffice/language": ["./src/packages/language/index.ts"],