entity limit client validation
This commit is contained in:
@@ -11,7 +11,11 @@ import { html, customElement, state, repeat, css, property, nothing } from '@umb
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import '../block-grid-entry/index.js';
|
||||
import { UmbSorterController, type UmbSorterConfig, type resolvePlacementArgs } from '@umbraco-cms/backoffice/sorter';
|
||||
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
|
||||
import {
|
||||
UmbFormControlMixin,
|
||||
UmbFormControlValidator,
|
||||
type UmbFormControlValidatorConfig,
|
||||
} from '@umbraco-cms/backoffice/validation';
|
||||
import type { UmbNumberRangeValueType } from '@umbraco-cms/backoffice/models';
|
||||
|
||||
/**
|
||||
@@ -128,6 +132,7 @@ export class UmbBlockGridEntriesElement extends UmbFormControlMixin(UmbLitElemen
|
||||
});
|
||||
|
||||
#context = new UmbBlockGridEntriesContext(this);
|
||||
#controlValidator: UmbFormControlValidator;
|
||||
|
||||
@property({ attribute: false })
|
||||
public set areaKey(value: string | null | undefined) {
|
||||
@@ -198,33 +203,66 @@ export class UmbBlockGridEntriesElement extends UmbFormControlMixin(UmbLitElemen
|
||||
'observeStylesheet',
|
||||
);
|
||||
});
|
||||
|
||||
this.#controlValidator = new UmbFormControlValidator(this, this /*, this.#dataPath*/);
|
||||
}
|
||||
|
||||
async #setupValidation() {
|
||||
async #getLimitValidation() {
|
||||
if (this._areaKey === null) {
|
||||
// This validation setup is not be as configurable as it should be, but it is a start. Alternatively we should consume the manager and observe the configuration. [NL]
|
||||
const manager = await this.#context.getManager();
|
||||
const config = manager.getEditorConfiguration();
|
||||
const min = config?.getValueByAlias<UmbNumberRangeValueType>('validationLimit')?.min ?? 0;
|
||||
const max = config?.getValueByAlias<UmbNumberRangeValueType>('validationLimit')?.max ?? Infinity;
|
||||
return { min, max };
|
||||
} else {
|
||||
return { min: 3, max: 4 };
|
||||
}
|
||||
}
|
||||
|
||||
this.addValidator(
|
||||
#rangeUnderflowValidator?: UmbFormControlValidatorConfig;
|
||||
#rangeOverflowValidator?: UmbFormControlValidatorConfig;
|
||||
async #setupValidation() {
|
||||
const rangeLimit = await this.#getLimitValidation();
|
||||
|
||||
console.log('setup validation', this);
|
||||
|
||||
if (this.#rangeUnderflowValidator) {
|
||||
this.removeValidator(this.#rangeUnderflowValidator);
|
||||
this.#rangeUnderflowValidator = undefined;
|
||||
}
|
||||
if (rangeLimit.min !== 0) {
|
||||
this.#rangeUnderflowValidator = this.addValidator(
|
||||
'rangeUnderflow',
|
||||
() => {
|
||||
return this.localize.term('validation_entriesShort', [min, min - (this._layoutEntries.length ?? 0)]);
|
||||
return this.localize.term(
|
||||
'validation_entriesShort',
|
||||
rangeLimit.min,
|
||||
rangeLimit.min - (this._layoutEntries.length ?? 0),
|
||||
);
|
||||
},
|
||||
() => {
|
||||
return (this._layoutEntries.length ?? 0) < min;
|
||||
return (this._layoutEntries.length ?? 0) < rangeLimit.min;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
this.addValidator(
|
||||
if (this.#rangeOverflowValidator) {
|
||||
this.removeValidator(this.#rangeOverflowValidator);
|
||||
this.#rangeOverflowValidator = undefined;
|
||||
}
|
||||
if (rangeLimit.max !== Infinity) {
|
||||
this.#rangeOverflowValidator = this.addValidator(
|
||||
'rangeOverflow',
|
||||
() => {
|
||||
return this.localize.term('validation_entriesExceed', [max, (this._layoutEntries.length ?? 0) - max]);
|
||||
return this.localize.term(
|
||||
'validation_entriesExceed',
|
||||
rangeLimit.max,
|
||||
(this._layoutEntries.length ?? 0) - rangeLimit.max,
|
||||
);
|
||||
},
|
||||
() => {
|
||||
return (this._layoutEntries.length ?? 0) > max;
|
||||
return (this._layoutEntries.length ?? 0) > rangeLimit.max;
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -247,6 +285,7 @@ export class UmbBlockGridEntriesElement extends UmbFormControlMixin(UmbLitElemen
|
||||
</umb-block-grid-entry>`,
|
||||
)}
|
||||
</div>
|
||||
<uui-form-validation-message .for=${this}></uui-form-validation-message>
|
||||
${this._canCreate ? this.#renderCreateButton() : nothing}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ export class UmbPropertyEditorUIBlockGridElement
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<umb-block-grid-entries
|
||||
return html` <umb-block-grid-entries
|
||||
.areaKey=${null}
|
||||
.layoutColumns=${this._layoutColumns}></umb-block-grid-entries>`;
|
||||
}
|
||||
|
||||
@@ -68,12 +68,13 @@ export class UmbValidationContext extends UmbContextBase<UmbValidationContext> i
|
||||
|
||||
const resultsStatus = await Promise.all(this.#validators.map((v) => v.validate())).then(
|
||||
() => Promise.resolve(true),
|
||||
() => Promise.reject(false),
|
||||
() => Promise.resolve(false),
|
||||
);
|
||||
|
||||
// If we have any messages then we are not valid, otherwise lets check the validation results: [NL]
|
||||
// This enables us to keep client validations though UI is not present anymore — because the client validations got defined as messages. [NL]
|
||||
const isValid = this.messages.getHasAnyMessages() ? false : resultsStatus;
|
||||
|
||||
this.#isValid = isValid;
|
||||
|
||||
if (isValid === false) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbControllerAlias, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbFormControlValidator extends UmbControllerBase implements UmbValidator {
|
||||
// The path to the data that this validator is validating. Public so the ValidationContext can access it.
|
||||
// The path to the data that this validator is validating.
|
||||
readonly #dataPath?: string;
|
||||
|
||||
#context?: typeof UMB_VALIDATION_CONTEXT.TYPE;
|
||||
|
||||
@@ -34,7 +34,11 @@ interface UmbFormControlValidatorConfig {
|
||||
}
|
||||
|
||||
export interface UmbFormControlMixinInterface<ValueType> extends HTMLElement {
|
||||
addValidator: (flagKey: FlagTypes, getMessageMethod: () => string, checkMethod: () => boolean) => void;
|
||||
addValidator: (
|
||||
flagKey: FlagTypes,
|
||||
getMessageMethod: () => string,
|
||||
checkMethod: () => boolean,
|
||||
) => UmbFormControlValidatorConfig;
|
||||
removeValidator: (obj: UmbFormControlValidatorConfig) => void;
|
||||
//static formAssociated: boolean;
|
||||
//protected getFormElement(): HTMLElement | undefined | null; // allows for null as it makes it simpler to just implement a querySelector as that might return null. [NL]
|
||||
@@ -56,7 +60,11 @@ export declare abstract class UmbFormControlMixinElement<ValueType>
|
||||
{
|
||||
protected _internals: ElementInternals;
|
||||
protected _runValidators(): void;
|
||||
addValidator: (flagKey: FlagTypes, getMessageMethod: () => string, checkMethod: () => boolean) => void;
|
||||
addValidator: (
|
||||
flagKey: FlagTypes,
|
||||
getMessageMethod: () => string,
|
||||
checkMethod: () => boolean,
|
||||
) => UmbFormControlValidatorConfig;
|
||||
removeValidator: (obj: UmbFormControlValidatorConfig) => void;
|
||||
protected addFormControlElement(element: UmbNativeFormControlElement): void;
|
||||
|
||||
@@ -209,7 +217,7 @@ export function UmbFormControlMixin<
|
||||
flagKey: flagKey,
|
||||
getMessageMethod: getMessageMethod,
|
||||
checkMethod: checkMethod,
|
||||
};
|
||||
} satisfies UmbFormControlValidatorConfig;
|
||||
this.#validators.push(validator);
|
||||
return validator;
|
||||
}
|
||||
|
||||
@@ -676,6 +676,7 @@ export class UmbDocumentWorkspaceContext
|
||||
// Create the validation repository if it does not exist. (we first create this here when we need it) [NL]
|
||||
this.#validationRepository ??= new UmbDocumentValidationRepository(this);
|
||||
|
||||
// We ask the server first to get a concatenated set of validation messages. So we see both front-end and back-end validation messages [NL]
|
||||
if (this.getIsNew()) {
|
||||
const parent = this.#parent.getValue();
|
||||
if (!parent) throw new Error('Parent is not set');
|
||||
|
||||
Reference in New Issue
Block a user