Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { html, customElement, css, state, when } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UMB_VALIDATION_CONTEXT, umbBindToValidation, UmbValidationContext } from '@umbraco-cms/backoffice/validation';
import type { UmbValidationMessage } from '@umbraco-cms/backoffice/validation';

@customElement('umb-example-validation-context-dashboard')
export class UmbExampleValidationContextDashboard extends UmbLitElement {

export class UmbExampleValidationContextDashboardElement extends UmbLitElement {
readonly validation = new UmbValidationContext(this);

@state()
Expand All @@ -20,7 +20,7 @@ export class UmbExampleValidationContextDashboard extends UmbLitElement {
country = '';

@state()
messages? : any[]
messages?: UmbValidationMessage[];

@state()
totalErrorCount = 0;
Expand All @@ -32,188 +32,199 @@ export class UmbExampleValidationContextDashboard extends UmbLitElement {
tab2ErrorCount = 0;

@state()
tab = "1";
tab = '1';

constructor() {
super();

this.consumeContext(UMB_VALIDATION_CONTEXT,(validationContext)=>{

this.observe(validationContext.messages.messages,(messages)=>{
this.messages = messages;
},'observeValidationMessages')
this.consumeContext(UMB_VALIDATION_CONTEXT, (validationContext) => {
this.observe(
validationContext.messages.messages,
(messages) => {
this.messages = messages;
},
'observeValidationMessages',
);

// Observe all errors
this.validation.messages.messagesOfPathAndDescendant('$.form').subscribe((value)=>{
this.totalErrorCount = [...new Set(value.map(x=>x.path))].length;
this.validation.messages.messagesOfPathAndDescendant('$.form').subscribe((value) => {
this.totalErrorCount = [...new Set(value.map((x) => x.path))].length;
});

// Observe errors for tab1, note that we only use part of the full JSONPath
this.validation.messages.messagesOfPathAndDescendant('$.form.tab1').subscribe((value)=>{
this.tab1ErrorCount = [...new Set(value.map(x=>x.path))].length;
this.validation.messages.messagesOfPathAndDescendant('$.form.tab1').subscribe((value) => {
this.tab1ErrorCount = [...new Set(value.map((x) => x.path))].length;
});

// Observe errors for tab2, note that we only use part of the full JSONPath
this.validation.messages.messagesOfPathAndDescendant('$.form.tab2').subscribe((value)=>{
this.tab2ErrorCount = [...new Set(value.map(x=>x.path))].length;
this.validation.messages.messagesOfPathAndDescendant('$.form.tab2').subscribe((value) => {
this.tab2ErrorCount = [...new Set(value.map((x) => x.path))].length;
});

});
});
}

#onTabChange(e:Event) {
#onTabChange(e: Event) {
this.tab = (e.target as HTMLElement).getAttribute('data-tab') as string;
}

#handleSave() {

// fake server validation-errors for all fields
if(this.name == '')
this.validation.messages.addMessage('server','$.form.tab1.name','Name server-error message','4875e113-cd0c-4c57-ac92-53d677ba31ec');
if(this.email == '')
this.validation.messages.addMessage('server','$.form.tab1.email','Email server-error message','a47e287b-4ce6-4e8b-8e05-614e7cec1a2a');
if(this.city == '')
this.validation.messages.addMessage('server','$.form.tab2.city','City server-error message','8dfc2f15-fb9a-463b-bcec-2c5d3ba2d07d');
if(this.country == '')
this.validation.messages.addMessage('server','$.form.tab2.country','Country server-error message','d98624f6-82a2-4e94-822a-776b44b01495');
if (this.name == '')
this.validation.messages.addMessage(
'server',
'$.form.tab1.name',
'Name server-error message',
'4875e113-cd0c-4c57-ac92-53d677ba31ec',
);
if (this.email == '')
this.validation.messages.addMessage(
'server',
'$.form.tab1.email',
'Email server-error message',
'a47e287b-4ce6-4e8b-8e05-614e7cec1a2a',
);
if (this.city == '')
this.validation.messages.addMessage(
'server',
'$.form.tab2.city',
'City server-error message',
'8dfc2f15-fb9a-463b-bcec-2c5d3ba2d07d',
);
if (this.country == '')
this.validation.messages.addMessage(
'server',
'$.form.tab2.country',
'Country server-error message',
'd98624f6-82a2-4e94-822a-776b44b01495',
);
}

override render() {
return html`
<uui-box>
This is a demo of how the Validation Context can be used to validate a form with multiple steps. Start typing in the form or press Save to trigger validation.
<hr/>
This is a demo of how the Validation Context can be used to validate a form with multiple steps. Start typing in
the form or press Save to trigger validation.
<hr />
Total errors: ${this.totalErrorCount}
<hr/>
<hr />
<uui-tab-group @click=${this.#onTabChange}>
<uui-tab ?active=${this.tab == '1'} data-tab="1">
<uui-tab ?active=${this.tab == '1'} data-tab="1">
Tab 1
${when(this.tab1ErrorCount,()=>html`
<uui-badge color="danger">${this.tab1ErrorCount}</uui-badge>
`)}
${when(this.tab1ErrorCount, () => html` <uui-badge color="invalid">${this.tab1ErrorCount}</uui-badge> `)}
</uui-tab>
<uui-tab ?active=${this.tab == '2'} data-tab="2">
<uui-tab ?active=${this.tab == '2'} data-tab="2">
Tab 2
${when(this.tab2ErrorCount,()=>html`
<uui-badge color="danger">${this.tab2ErrorCount}</uui-badge>
`)}
${when(this.tab2ErrorCount, () => html` <uui-badge color="invalid">${this.tab2ErrorCount}</uui-badge> `)}
</uui-tab>
</uui-tab-group>
</uui-tab-group>

${when(this.tab=='1',()=>html`
${this.#renderTab1()}
`)}
${when(this.tab=='2',()=>html`
${this.#renderTab2()}
`)}
${when(this.tab == '1', () => html` ${this.#renderTab1()} `)}
${when(this.tab == '2', () => html` ${this.#renderTab2()} `)}

<uui-button look="primary" color="positive" @click=${this.#handleSave}>Save</uui-button>
<hr/>
<hr />
<h3>Validation Context Messages</h3>
<pre>${JSON.stringify(this.messages ?? [],null,3)}</pre>
<pre>${JSON.stringify(this.messages ?? [], null, 3)}</pre>
</uui-box>
`
`;
}

#renderTab1() {
return html`
<uui-form>
<form>
<div>
<label>Name</label>
<uui-form-validation-message>
<uui-input
type="text"
.value=${this.name}
@input=${(e: InputEvent)=>this.name = (e.target as HTMLInputElement).value}
${umbBindToValidation(this,'$.form.tab1.name',this.name)}
required></uui-input>
</uui-form-validation-message>
<label>Name</label>
<uui-form-validation-message>
<uui-input
type="text"
.value=${this.name}
@input=${(e: InputEvent) => (this.name = (e.target as HTMLInputElement).value)}
${umbBindToValidation(this, '$.form.tab1.name', this.name)}
required></uui-input>
</uui-form-validation-message>
</div>
<label>E-mail</label>
<uui-form-validation-message>
<uui-input
type="email"
.value=${this.email}
@input=${(e: InputEvent)=>this.email = (e.target as HTMLInputElement).value}
${umbBindToValidation(this,'$.form.tab1.email',this.email)}
@input=${(e: InputEvent) => (this.email = (e.target as HTMLInputElement).value)}
${umbBindToValidation(this, '$.form.tab1.email', this.email)}
required></uui-input>
</uui-form-validation-message>
</form>
</uui-form>
`
`;
}

#renderTab2() {
return html`
<uui-form>
<form>
<div>
<label>City</label>
<uui-form-validation-message>
<uui-input
type="text"
.value=${this.city}
@input=${(e: InputEvent)=>this.city = (e.target as HTMLInputElement).value}
${umbBindToValidation(this,'$.form.tab2.city',this.city)}
required></uui-input>
</uui-form-validation-message>
<label>City</label>
<uui-form-validation-message>
<uui-input
type="text"
.value=${this.city}
@input=${(e: InputEvent) => (this.city = (e.target as HTMLInputElement).value)}
${umbBindToValidation(this, '$.form.tab2.city', this.city)}
required></uui-input>
</uui-form-validation-message>
</div>
<label>Country</label>
<uui-form-validation-message>
<uui-input
type="text"
.value=${this.country}
@input=${(e: InputEvent)=>this.country = (e.target as HTMLInputElement).value}
${umbBindToValidation(this,'$.form.tab2.country',this.country)}
@input=${(e: InputEvent) => (this.country = (e.target as HTMLInputElement).value)}
${umbBindToValidation(this, '$.form.tab2.country', this.country)}
required></uui-input>
</uui-form-validation-message>
</form>
</uui-form>
`
`;
}



static override styles = [css`

uui-badge {
top:0;
right:0;
font-size:10px;
min-width:17px;
min-height:17px;

}

label {
display:block;
}

uui-box {
margin:20px;
}

uui-button {
margin-top:1rem;
}

pre {
text-align:left;
padding:10px;
border:1px dotted #6f6f6f;
background: #f2f2f2;
font-size: 11px;
line-height: 1.3em;
}

`]
static override styles = [
css`
uui-badge {
top: 0;
right: 0;
font-size: 10px;
min-width: 17px;
min-height: 17px;
}

label {
display: block;
}

uui-box {
margin: 20px;
}

uui-button {
margin-top: 1rem;
}

pre {
text-align: left;
padding: 10px;
border: 1px dotted #6f6f6f;
background: #f2f2f2;
font-size: 11px;
line-height: 1.3em;
}
`,
];
}

export default UmbExampleValidationContextDashboard;
export default UmbExampleValidationContextDashboardElement;

declare global {
interface HTMLElementTagNameMap {
'umb-example-validation-context-dashboard': UmbExampleValidationContextDashboard;
'umb-example-validation-context-dashboard': UmbExampleValidationContextDashboardElement;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ export class UmbBlockGridEntriesElement extends UmbFormControlMixin(UmbLitElemen
return html`
<uui-button
look="placeholder"
color=${this.pristine === false && this.validity.valid === false ? 'invalid' : 'default'}
label=${this._configCreateLabel ?? this._createLabel ?? ''}
href=${this.#context.getPathForCreateBlock(-1) ?? ''}
?disabled=${this._isReadOnly}></uui-button>
Expand Down Expand Up @@ -492,13 +493,6 @@ export class UmbBlockGridEntriesElement extends UmbFormControlMixin(UmbLitElemen
--umb-block-grid--create-button--is-dragging--variable: var(--umb-block-grid--is-dragging) none;
display: var(--umb-block-grid--create-button--is-dragging--variable, grid);
}
:host(:not([pristine]):invalid) #createButton {
--uui-button-contrast: var(--uui-color-danger);
--uui-button-contrast-hover: var(--uui-color-danger);
--uui-color-default-emphasis: var(--uui-color-danger);
--uui-button-border-color: var(--uui-color-danger);
--uui-button-border-color-hover: var(--uui-color-danger);
}

.umb-block-grid__layout-container[data-area-length='0'] {
--umb-block-grid--layout-container--is-dragging--variable: var(--umb-block-grid--is-dragging) 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
>
${this.#renderActionBar()}
${!this._showContentEdit && this._contentInvalid
? html`<uui-badge attention color="danger" label="Invalid content">!</uui-badge>`
? html`<uui-badge attention color="invalid" label="Invalid content">!</uui-badge>`
: nothing}
${this._invalidLocation
? html`<uui-tag id="invalidLocation" color="danger"
Expand Down Expand Up @@ -562,7 +562,7 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
href=${this._workspaceEditContentPath}>
<uui-icon name=${this._exposed === false ? 'icon-add' : 'icon-edit'}></uui-icon>
${this._contentInvalid
? html`<uui-badge attention color="danger" label="Invalid content">!</uui-badge>`
? html`<uui-badge attention color="invalid" label="Invalid content">!</uui-badge>`
: nothing}
</uui-button>`
: this._showContentEdit === false && this._exposed === false
Expand All @@ -581,11 +581,11 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
? html`<uui-button
label="Edit settings"
look="secondary"
color=${this._settingsInvalid ? 'danger' : ''}
color=${this._settingsInvalid ? 'invalid' : ''}
href=${this._workspaceEditSettingsPath}>
<uui-icon name="icon-settings"></uui-icon>
${this._settingsInvalid
? html`<uui-badge attention color="danger" label="Invalid settings">!</uui-badge>`
? html`<uui-badge attention color="invalid" label="Invalid settings">!</uui-badge>`
: nothing}
</uui-button>`
: nothing}
Expand Down Expand Up @@ -638,7 +638,7 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
:host([location-invalid])::after,
:host([settings-invalid])::after,
:host([content-invalid])::after {
border-color: var(--uui-color-danger);
border-color: var(--uui-color-invalid);
}

#invalidLocation {
Expand Down
Loading
Loading