From 162ac746c125f43349c25f6a3403e16ef82bd676 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 20 Jan 2023 15:06:34 +0100 Subject: [PATCH] add validation --- .../input-document-picker.element.ts | 1 + .../input-multiple-text-string.element.ts | 91 +++++++++++++++---- ...-editor-ui-multiple-text-string.element.ts | 4 +- 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts index 31432bdac6..cdae66abff 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts @@ -56,6 +56,7 @@ export class UmbInputDocumentPickerElement extends FormControlMixin(UmbLitElemen @property({ type: String, attribute: 'min-message' }) maxMessage = 'This field exceeds the allowed amount of items'; + // TODO: do we need both selectedKeys and value? If we just use value we follow the same pattern as native form controls. private _selectedKeys: Array = []; public get selectedKeys(): Array { return this._selectedKeys; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts index 8c076836c0..2bf0f09016 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts @@ -2,9 +2,11 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; +import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; import { UUIInputElement, UUIInputEvent } from '@umbraco-ui/uui-input'; import { UmbLitElement } from '@umbraco-cms/element'; import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from 'src/core/modal'; +import { UmbChangeEvent } from 'src/core/events/change.event'; export type MultipleTextStringValue = Array; @@ -16,7 +18,7 @@ export interface MultipleTextStringValueItem { * @element umb-input-multiple-text-string */ @customElement('umb-input-multiple-text-string') -export class UmbInputMultipleTextStringElement extends UmbLitElement { +export class UmbInputMultipleTextStringElement extends FormControlMixin(UmbLitElement) { static styles = [ UUITextStyles, css` @@ -37,35 +39,88 @@ export class UmbInputMultipleTextStringElement extends UmbLitElement { `, ]; - @state() - private _value: MultipleTextStringValue = []; + /** + * This is a minimum amount of selected items in this input. + * @type {number} + * @attr + * @default undefined + */ + @property({ type: Number }) + min?: number; - @property({ type: Array }) - public get value(): MultipleTextStringValue { - return this._value; - } - public set value(value: MultipleTextStringValue) { - this._value = value || []; - } + /** + * Min validation message. + * @type {boolean} + * @attr + * @default + */ + @property({ type: String, attribute: 'min-message' }) + minMessage = 'This field need more items'; + + /** + * This is a maximum amount of selected items in this input. + * @type {number} + * @attr + * @default undefined + */ + @property({ type: Number }) + max?: number; + + /** + * Max validation message. + * @type {boolean} + * @attr + * @default + */ + @property({ type: String, attribute: 'min-message' }) + maxMessage = 'This field exceeds the allowed amount of items'; private _modalService?: UmbModalService; constructor() { super(); + this.addValidator( + 'rangeUnderflow', + () => this.minMessage, + () => !!this.min && this._items.length < this.min + ); + this.addValidator( + 'rangeOverflow', + () => this.maxMessage, + () => !!this.max && this._items.length > this.max + ); + this.consumeContext(UMB_MODAL_SERVICE_CONTEXT_TOKEN, (modalService) => { this._modalService = modalService; }); } + @state() + private _items: MultipleTextStringValue = []; + + @property({ type: Array }) + public get items(): MultipleTextStringValue { + return this._items; + } + public set items(items: MultipleTextStringValue) { + this._items = items || []; + } + + @property() + public set value(itemsString: string) { + // TODO: implement value setter and getter + throw new Error('Not implemented'); + } + #onAdd() { - this._value = [...this._value, { value: '' }]; - this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: false, cancelable: false })); + this._items = [...this._items, { value: '' }]; + this.dispatchEvent(new UmbChangeEvent()); this.#focusNewItem(); } #onDelete(index: number) { - const item = this._value[index]; + const item = this._items[index]; const modalHandler = this._modalService?.confirm({ headline: `Delete ${item.value || 'item'}`, @@ -82,7 +137,7 @@ export class UmbInputMultipleTextStringElement extends UmbLitElement { #onInput(event: UUIInputEvent, currentIndex: number) { const target = event.currentTarget as UUIInputElement; const value = target.value as string; - this._value = this._value.map((item, index) => (index === currentIndex ? { value } : item)); + this._items = this._items.map((item, index) => (index === currentIndex ? { value } : item)); this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: false, cancelable: false })); } @@ -94,10 +149,14 @@ export class UmbInputMultipleTextStringElement extends UmbLitElement { } #deleteItem(itemIndex: number) { - this._value = this._value.filter((item, index) => index !== itemIndex); + this._items = this._items.filter((item, index) => index !== itemIndex); this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: false, cancelable: false })); } + protected getFormElement() { + return undefined; + } + render() { return html` ${this._renderItems()} @@ -108,7 +167,7 @@ export class UmbInputMultipleTextStringElement extends UmbLitElement { private _renderItems() { return html` ${repeat( - this._value, + this._items, (item, index) => index, (item, index) => html`${this._renderItem(item, index)}` )} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multiple-text-string/property-editor-ui-multiple-text-string.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multiple-text-string/property-editor-ui-multiple-text-string.element.ts index 5d203c28f3..6d8d5d9945 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multiple-text-string/property-editor-ui-multiple-text-string.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multiple-text-string/property-editor-ui-multiple-text-string.element.ts @@ -40,13 +40,13 @@ export class UmbPropertyEditorUIMultipleTextStringElement extends UmbLitElement #onChange(event: UmbChangeEvent) { event.stopPropagation(); const target = event.currentTarget as UmbInputMultipleTextStringElement; - this.value = target.value; + this.value = target.items; this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { return html``;