|
| 1 | +import { html, customElement, css, state, when } from '@umbraco-cms/backoffice/external/lit'; |
| 2 | +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; |
| 3 | +import { UMB_VALIDATION_CONTEXT, umbBindToValidation, UmbValidationContext } from '@umbraco-cms/backoffice/validation'; |
| 4 | + |
| 5 | +@customElement('umb-example-validation-context-dashboard') |
| 6 | +export class UmbExampleValidationContextDashboard extends UmbLitElement { |
| 7 | + |
| 8 | + readonly validation = new UmbValidationContext(this); |
| 9 | + |
| 10 | + @state() |
| 11 | + name = ''; |
| 12 | + |
| 13 | + @state() |
| 14 | + email = ''; |
| 15 | + |
| 16 | + @state() |
| 17 | + city = ''; |
| 18 | + |
| 19 | + @state() |
| 20 | + country = ''; |
| 21 | + |
| 22 | + @state() |
| 23 | + messages? : any[] |
| 24 | + |
| 25 | + @state() |
| 26 | + totalErrorCount = 0; |
| 27 | + |
| 28 | + @state() |
| 29 | + tab1ErrorCount = 0; |
| 30 | + |
| 31 | + @state() |
| 32 | + tab2ErrorCount = 0; |
| 33 | + |
| 34 | + @state() |
| 35 | + tab = "1"; |
| 36 | + |
| 37 | + constructor() { |
| 38 | + super(); |
| 39 | + |
| 40 | + this.consumeContext(UMB_VALIDATION_CONTEXT,(validationContext)=>{ |
| 41 | + |
| 42 | + this.observe(validationContext.messages.messages,(messages)=>{ |
| 43 | + this.messages = messages; |
| 44 | + },'observeValidationMessages') |
| 45 | + |
| 46 | + // Observe all errors |
| 47 | + this.validation.messages.messagesOfPathAndDescendant('$.form').subscribe((value)=>{ |
| 48 | + this.totalErrorCount = [...new Set(value.map(x=>x.path))].length; |
| 49 | + }); |
| 50 | + |
| 51 | + // Observe errors for tab1, note that we only use part of the full JSONPath |
| 52 | + this.validation.messages.messagesOfPathAndDescendant('$.form.tab1').subscribe((value)=>{ |
| 53 | + this.tab1ErrorCount = [...new Set(value.map(x=>x.path))].length; |
| 54 | + }); |
| 55 | + |
| 56 | + // Observe errors for tab2, note that we only use part of the full JSONPath |
| 57 | + this.validation.messages.messagesOfPathAndDescendant('$.form.tab2').subscribe((value)=>{ |
| 58 | + this.tab2ErrorCount = [...new Set(value.map(x=>x.path))].length; |
| 59 | + }); |
| 60 | + |
| 61 | + }); |
| 62 | + } |
| 63 | + |
| 64 | + #onTabChange(e:Event) { |
| 65 | + this.tab = (e.target as HTMLElement).getAttribute('data-tab') as string; |
| 66 | + } |
| 67 | + |
| 68 | + #handleSave() { |
| 69 | + |
| 70 | + // fake server validation-errors for all fields |
| 71 | + if(this.name == '') |
| 72 | + this.validation.messages.addMessage('server','$.form.tab1.name','Name server-error message','4875e113-cd0c-4c57-ac92-53d677ba31ec'); |
| 73 | + if(this.email == '') |
| 74 | + this.validation.messages.addMessage('server','$.form.tab1.email','Email server-error message','a47e287b-4ce6-4e8b-8e05-614e7cec1a2a'); |
| 75 | + if(this.city == '') |
| 76 | + this.validation.messages.addMessage('server','$.form.tab2.city','City server-error message','8dfc2f15-fb9a-463b-bcec-2c5d3ba2d07d'); |
| 77 | + if(this.country == '') |
| 78 | + this.validation.messages.addMessage('server','$.form.tab2.country','Country server-error message','d98624f6-82a2-4e94-822a-776b44b01495'); |
| 79 | + } |
| 80 | + |
| 81 | + override render() { |
| 82 | + return html` |
| 83 | + <uui-box> |
| 84 | + 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. |
| 85 | + <hr/> |
| 86 | + Total errors: ${this.totalErrorCount} |
| 87 | + <hr/> |
| 88 | + <uui-tab-group @click=${this.#onTabChange}> |
| 89 | + <uui-tab ?active=${this.tab == '1'} data-tab="1"> |
| 90 | + Tab 1 |
| 91 | + ${when(this.tab1ErrorCount,()=>html` |
| 92 | + <uui-badge color="danger">${this.tab1ErrorCount}</uui-badge> |
| 93 | + `)} |
| 94 | + </uui-tab> |
| 95 | + <uui-tab ?active=${this.tab == '2'} data-tab="2"> |
| 96 | + Tab 2 |
| 97 | + ${when(this.tab2ErrorCount,()=>html` |
| 98 | + <uui-badge color="danger">${this.tab2ErrorCount}</uui-badge> |
| 99 | + `)} |
| 100 | + </uui-tab> |
| 101 | + </uui-tab-group> |
| 102 | +
|
| 103 | + ${when(this.tab=='1',()=>html` |
| 104 | + ${this.#renderTab1()} |
| 105 | + `)} |
| 106 | + ${when(this.tab=='2',()=>html` |
| 107 | + ${this.#renderTab2()} |
| 108 | + `)} |
| 109 | +
|
| 110 | + <uui-button look="primary" color="positive" @click=${this.#handleSave}>Save</uui-button> |
| 111 | + <hr/> |
| 112 | + <h3>Validation Context Messages</h3> |
| 113 | + <pre>${JSON.stringify(this.messages ?? [],null,3)}</pre> |
| 114 | + </uui-box> |
| 115 | + ` |
| 116 | + } |
| 117 | + |
| 118 | + #renderTab1() { |
| 119 | + return html` |
| 120 | + <uui-form> |
| 121 | + <form> |
| 122 | + <div> |
| 123 | + <label>Name</label> |
| 124 | + <uui-form-validation-message> |
| 125 | + <uui-input |
| 126 | + type="text" |
| 127 | + .value=${this.name} |
| 128 | + @input=${(e: InputEvent)=>this.name = (e.target as HTMLInputElement).value} |
| 129 | + ${umbBindToValidation(this,'$.form.tab1.name',this.name)} |
| 130 | + required></uui-input> |
| 131 | + </uui-form-validation-message> |
| 132 | + </div> |
| 133 | + <label>E-mail</label> |
| 134 | + <uui-form-validation-message> |
| 135 | + <uui-input |
| 136 | + type="email" |
| 137 | + .value=${this.email} |
| 138 | + @input=${(e: InputEvent)=>this.email = (e.target as HTMLInputElement).value} |
| 139 | + ${umbBindToValidation(this,'$.form.tab1.email',this.email)} |
| 140 | + required></uui-input> |
| 141 | + </uui-form-validation-message> |
| 142 | + </form> |
| 143 | + </uui-form> |
| 144 | + ` |
| 145 | + } |
| 146 | + |
| 147 | + #renderTab2() { |
| 148 | + return html` |
| 149 | + <uui-form> |
| 150 | + <form> |
| 151 | + <div> |
| 152 | + <label>City</label> |
| 153 | + <uui-form-validation-message> |
| 154 | + <uui-input |
| 155 | + type="text" |
| 156 | + .value=${this.city} |
| 157 | + @input=${(e: InputEvent)=>this.city = (e.target as HTMLInputElement).value} |
| 158 | + ${umbBindToValidation(this,'$.form.tab2.city',this.city)} |
| 159 | + required></uui-input> |
| 160 | + </uui-form-validation-message> |
| 161 | + </div> |
| 162 | + <label>Country</label> |
| 163 | + <uui-form-validation-message> |
| 164 | + <uui-input |
| 165 | + type="text" |
| 166 | + .value=${this.country} |
| 167 | + @input=${(e: InputEvent)=>this.country = (e.target as HTMLInputElement).value} |
| 168 | + ${umbBindToValidation(this,'$.form.tab2.country',this.country)} |
| 169 | + required></uui-input> |
| 170 | + </uui-form-validation-message> |
| 171 | + </form> |
| 172 | + </uui-form> |
| 173 | + ` |
| 174 | + } |
| 175 | + |
| 176 | + |
| 177 | + |
| 178 | + static override styles = [css` |
| 179 | +
|
| 180 | + uui-badge { |
| 181 | + top:0; |
| 182 | + right:0; |
| 183 | + font-size:10px; |
| 184 | + min-width:17px; |
| 185 | + min-height:17px; |
| 186 | +
|
| 187 | + } |
| 188 | +
|
| 189 | + label { |
| 190 | + display:block; |
| 191 | + } |
| 192 | +
|
| 193 | + uui-box { |
| 194 | + margin:20px; |
| 195 | + } |
| 196 | +
|
| 197 | + uui-button { |
| 198 | + margin-top:1rem; |
| 199 | + } |
| 200 | +
|
| 201 | + pre { |
| 202 | + text-align:left; |
| 203 | + padding:10px; |
| 204 | + border:1px dotted #6f6f6f; |
| 205 | + background: #f2f2f2; |
| 206 | + font-size: 11px; |
| 207 | + line-height: 1.3em; |
| 208 | + } |
| 209 | +
|
| 210 | + `] |
| 211 | +} |
| 212 | + |
| 213 | +export default UmbExampleValidationContextDashboard; |
| 214 | + |
| 215 | +declare global { |
| 216 | + interface HTMLElementTagNameMap { |
| 217 | + 'umb-example-validation-context-dashboard': UmbExampleValidationContextDashboard; |
| 218 | + } |
| 219 | +} |
0 commit comments