@schukai/monster 3.69.2 → 3.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -4
- package/package.json +1 -1
- package/source/components/datatable/dataset.mjs +278 -202
- package/source/components/datatable/datasource/dom.mjs +1 -1
- package/source/components/datatable/datasource/rest.mjs +2 -2
- package/source/components/datatable/filter.mjs +1 -0
- package/source/components/datatable/save-button.mjs +1 -1
- package/source/components/datatable/style/datatable.pcss +1 -1
- package/source/components/datatable/style/filter-controls-defaults.pcss +1 -1
- package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +8 -17
- package/source/components/form/context-error.mjs +2 -0
- package/source/components/form/context-help.mjs +1 -0
- package/source/components/form/field-set.mjs +222 -225
- package/source/components/form/form.mjs +192 -545
- package/source/components/form/select.mjs +24 -9
- package/source/components/form/style/field-set.pcss +84 -7
- package/source/components/form/style/form.pcss +5 -3
- package/source/components/form/style/select.pcss +5 -4
- package/source/components/form/stylesheet/field-set.mjs +7 -14
- package/source/components/form/stylesheet/form.mjs +8 -17
- package/source/components/form/stylesheet/select.mjs +7 -14
- package/source/components/layout/style/collapse.pcss +0 -2
- package/source/components/layout/stylesheet/collapse.mjs +7 -14
- package/source/components/style/form.pcss +66 -3
- package/source/components/style/mixin/property.pcss +8 -1
- package/source/components/style/typography.pcss +4 -12
- package/source/components/stylesheet/form.mjs +8 -17
- package/source/components/stylesheet/mixin/form.mjs +7 -16
- package/source/components/stylesheet/mixin/property.mjs +6 -13
- package/source/components/stylesheet/typography.mjs +7 -16
- package/source/data/datasource/server/restapi.mjs +182 -180
- package/source/dom/customelement.mjs +4 -0
- package/source/dom/updater.mjs +1 -1
- package/source/types/tokenlist.mjs +2 -2
- package/test/cases/components/form/form.mjs +1 -182
- package/test/cases/components/host/details.mjs +1 -1
- package/test/cases/components/host/host.mjs +1 -1
- package/test/cases/components/host/overlay.mjs +1 -1
- package/test/cases/dom/customcontrol.mjs +1 -1
- package/test/cases/dom/customelement.mjs +2 -2
- package/source/components/style/mixin/form.pcss +0 -242
@@ -12,577 +12,224 @@
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
13
13
|
*/
|
14
14
|
|
15
|
-
import {
|
16
|
-
import {
|
17
|
-
import {
|
18
|
-
import {
|
19
|
-
import {
|
20
|
-
import {
|
21
|
-
import {
|
22
|
-
import {
|
15
|
+
import {instanceSymbol} from "../../constants.mjs";
|
16
|
+
import {internalSymbol} from "../../constants.mjs";
|
17
|
+
import {TokenList} from "../../types/tokenlist.mjs";
|
18
|
+
import {DeadMansSwitch} from "../../util/deadmansswitch.mjs";
|
19
|
+
import {DataSet} from "../datatable/dataset.mjs";
|
20
|
+
//import { Datasource } from "../../data/datasource.mjs";
|
21
|
+
import {RestAPI} from "../../data/datasource/server/restapi.mjs";
|
22
|
+
import {WebConnect} from "../../data/datasource/server/webconnect.mjs";
|
23
|
+
import {WriteError} from "../../data/datasource/server/restapi/writeerror.mjs";
|
24
|
+
import {LocalStorage} from "../../data/datasource/storage/localstorage.mjs";
|
25
|
+
import {SessionStorage} from "../../data/datasource/storage/sessionstorage.mjs";
|
23
26
|
import {
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
ATTRIBUTE_DISABLED,
|
28
|
+
ATTRIBUTE_ERRORMESSAGE,
|
29
|
+
ATTRIBUTE_PREFIX,
|
30
|
+
ATTRIBUTE_UPDATER_ATTRIBUTES,
|
31
|
+
ATTRIBUTE_UPDATER_INSERT,
|
32
|
+
ATTRIBUTE_UPDATER_REMOVE,
|
33
|
+
ATTRIBUTE_UPDATER_REPLACE,
|
31
34
|
} from "../../dom/constants.mjs";
|
32
35
|
import {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
36
|
+
assembleMethodSymbol,
|
37
|
+
CustomElement,
|
38
|
+
registerCustomElement,
|
39
|
+
getSlottedElements,
|
37
40
|
} from "../../dom/customelement.mjs";
|
38
|
-
import {
|
39
|
-
import {
|
40
|
-
import {
|
41
|
-
import {
|
42
|
-
import {
|
43
|
-
import {
|
41
|
+
import {addObjectWithUpdaterToElement} from "../../dom/updater.mjs";
|
42
|
+
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
43
|
+
import {isFunction, isString} from "../../types/is.mjs";
|
44
|
+
import {Observer} from "../../types/observer.mjs";
|
45
|
+
import {ProxyObserver} from "../../types/proxyobserver.mjs";
|
46
|
+
import {Processing} from "../../util/processing.mjs";
|
47
|
+
import {datasourceLinkedElementSymbol, handleDataSourceChanges} from "../datatable/util.mjs";
|
48
|
+
import {MessageStateButton} from "./message-state-button.mjs";
|
44
49
|
import {
|
45
|
-
|
46
|
-
|
50
|
+
ATTRIBUTE_FORM_DATASOURCE,
|
51
|
+
ATTRIBUTE_FORM_DATASOURCE_ARGUMENTS,
|
47
52
|
} from "./constants.mjs";
|
48
|
-
import {
|
49
|
-
import {
|
53
|
+
import {StateButton} from "./state-button.mjs";
|
54
|
+
import {FormStyleSheet} from "./stylesheet/form.mjs";
|
50
55
|
|
51
|
-
export {
|
56
|
+
export {Form};
|
52
57
|
|
53
|
-
/**
|
54
|
-
* @private
|
55
|
-
* @since 3.1.0
|
56
|
-
* @type {string}
|
57
|
-
*/
|
58
|
-
const ATTRIBUTE_FORM_DATASOURCE_ACTION = `${ATTRIBUTE_PREFIX}datasource-action`;
|
59
|
-
|
60
|
-
/**
|
61
|
-
* Form data is the internal representation of the form data
|
62
|
-
*
|
63
|
-
* @private
|
64
|
-
* @type {symbol}
|
65
|
-
* @since 1.7.0
|
66
|
-
*/
|
67
|
-
const formDataSymbol = Symbol.for(
|
68
|
-
"@schukai/monster/components/form/form@@formdata",
|
69
|
-
);
|
70
|
-
|
71
|
-
/**
|
72
|
-
* @private
|
73
|
-
* @type {symbol}
|
74
|
-
* @since 2.8.0
|
75
|
-
*/
|
76
|
-
const formDataUpdaterSymbol = Symbol.for(
|
77
|
-
"@schukai/component-form/form@@formdata-updater-link",
|
78
|
-
);
|
79
58
|
|
80
59
|
/**
|
81
60
|
* @private
|
82
61
|
* @type {symbol}
|
83
|
-
* @since 1.7.0
|
84
|
-
*/
|
85
|
-
const formElementSymbol = Symbol.for(
|
86
|
-
"@schukai/component-form/form@@form-element",
|
87
|
-
);
|
88
|
-
|
89
|
-
/**
|
90
|
-
* @private
|
91
|
-
* @type {symbol}
|
92
|
-
* @since 2.5.0
|
93
|
-
*/
|
94
|
-
const registeredDatasourcesSymbol = Symbol.for(
|
95
|
-
"@schukai/component-form/form@@registered-datasources",
|
96
|
-
);
|
97
|
-
|
98
|
-
/**
|
99
|
-
* @private
|
100
|
-
* @since 1.7.0
|
101
|
-
* @type {string}
|
102
|
-
*/
|
103
|
-
const PROPERTY_VALIDATION_KEY = "__validation";
|
104
|
-
|
105
|
-
/**
|
106
|
-
* This CustomControl creates a form element with a variety of options.
|
107
|
-
*
|
108
|
-
* <img src="./images/form.png">
|
109
|
-
*
|
110
|
-
* Dependencies: the system uses functions of the [monsterjs](https://monsterjs.org/) library.
|
111
|
-
*
|
112
|
-
* You can create this control either by specifying the HTML tag `<monster-form />` directly in the HTML or using
|
113
|
-
* Javascript via the `document.createElement('monster-form');` method.
|
114
|
-
*
|
115
|
-
* ```html
|
116
|
-
* <monster-form></monster-form>
|
117
|
-
* ```
|
118
|
-
*
|
119
|
-
* Or you can create this CustomControl directly in Javascript:
|
120
|
-
*
|
121
|
-
* ```js
|
122
|
-
* import {Form} from '@schukai/component-form/source/form.js';
|
123
|
-
* document.createElement('monster-form');
|
124
|
-
* ```
|
125
|
-
*
|
126
|
-
* @startuml form.png
|
127
|
-
* skinparam monochrome true
|
128
|
-
* skinparam shadowing false
|
129
|
-
* HTMLElement <|-- CustomElement
|
130
|
-
* CustomElement <|-- Form
|
131
|
-
* @enduml
|
132
|
-
*
|
133
|
-
* @since 1.6.0
|
134
|
-
* @copyright schukai GmbH
|
135
|
-
* @memberOf Monster.Components.Form
|
136
|
-
* @summary A configurable form control
|
137
62
|
*/
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
this.removeAttribute(ATTRIBUTE_DISABLED);
|
239
|
-
throw e;
|
240
|
-
}
|
241
|
-
}
|
242
|
-
|
243
|
-
/**
|
244
|
-
*
|
245
|
-
* @return {Monster.Components.Form.Form}
|
246
|
-
*/
|
247
|
-
[assembleMethodSymbol]() {
|
248
|
-
super[assembleMethodSymbol]();
|
249
|
-
|
250
|
-
initControlReferences.call(this);
|
251
|
-
initDatasource.call(this);
|
252
|
-
initUpdater.call(this);
|
253
|
-
initObserver.call(this);
|
254
|
-
|
255
|
-
return this;
|
256
|
-
}
|
257
|
-
|
258
|
-
/**
|
259
|
-
*
|
260
|
-
* @return {*}
|
261
|
-
*/
|
262
|
-
getValues() {
|
263
|
-
return this[formDataSymbol].getSubject();
|
264
|
-
}
|
265
|
-
|
266
|
-
/**
|
267
|
-
*
|
268
|
-
* @return {string}
|
269
|
-
*/
|
270
|
-
static getTag() {
|
271
|
-
return "monster-form";
|
272
|
-
}
|
273
|
-
|
274
|
-
/**
|
275
|
-
*
|
276
|
-
* @return {CSSStyleSheet}
|
277
|
-
*/
|
278
|
-
static getCSSStyleSheet() {
|
279
|
-
return [FormStyleSheet];
|
280
|
-
}
|
281
|
-
|
282
|
-
static [registeredDatasourcesSymbol] = new Map([
|
283
|
-
["restapi", RestAPI],
|
284
|
-
["localstorage", LocalStorage],
|
285
|
-
["sessionstorage", SessionStorage],
|
286
|
-
["webconnect", WebConnect],
|
287
|
-
]);
|
288
|
-
|
289
|
-
/**
|
290
|
-
* Register a new datasource
|
291
|
-
*
|
292
|
-
* @param {string} name
|
293
|
-
* @param {Monster.Data.Datasource} datasource
|
294
|
-
*/
|
295
|
-
static registerDatasource(name, datasource) {
|
296
|
-
Form[registeredDatasourcesSymbol].set(name, datasource);
|
297
|
-
}
|
298
|
-
|
299
|
-
/**
|
300
|
-
* Unregister a registered datasource
|
301
|
-
*
|
302
|
-
* @param {string} name
|
303
|
-
*/
|
304
|
-
static unregisterDatasource(name) {
|
305
|
-
Form[registeredDatasourcesSymbol].delete(name);
|
306
|
-
}
|
307
|
-
|
308
|
-
/**
|
309
|
-
* Get registered data sources
|
310
|
-
*
|
311
|
-
* @return {Map}
|
312
|
-
*/
|
313
|
-
static getDatasources() {
|
314
|
-
return Form[registeredDatasourcesSymbol];
|
315
|
-
}
|
316
|
-
|
317
|
-
/**
|
318
|
-
* Run reportValidation on all child html form controls.
|
319
|
-
*
|
320
|
-
* @since 2.10.0
|
321
|
-
* @returns {boolean}
|
322
|
-
*/
|
323
|
-
reportValidity() {
|
324
|
-
let valid = true;
|
325
|
-
|
326
|
-
const selector = this.getOption("reportValidity.selector");
|
327
|
-
const nodes = getSlottedElements.call(this, selector);
|
328
|
-
nodes.forEach((node) => {
|
329
|
-
if (typeof node.reportValidity === "function") {
|
330
|
-
if (node.reportValidity() === false) {
|
331
|
-
valid = false;
|
332
|
-
}
|
333
|
-
}
|
334
|
-
});
|
335
|
-
|
336
|
-
return valid;
|
337
|
-
}
|
338
|
-
}
|
63
|
+
const debounceCallbackSymbol = Symbol("timerCallback");
|
64
|
+
|
65
|
+
class Form extends DataSet {
|
66
|
+
|
67
|
+
/**
|
68
|
+
*
|
69
|
+
* @returns {{shadowMode: string, templates: {main: *}, display: string, disabled: boolean, delegatesFocus: boolean, templateMapping: {}} & {templates: {main: string}, classes: {form: string}}}
|
70
|
+
*/
|
71
|
+
get defaults() {
|
72
|
+
const obj = Object.assign(
|
73
|
+
{},
|
74
|
+
super.defaults,
|
75
|
+
{
|
76
|
+
templates: {
|
77
|
+
main: getTemplate(),
|
78
|
+
},
|
79
|
+
|
80
|
+
classes: {
|
81
|
+
form: "",
|
82
|
+
},
|
83
|
+
|
84
|
+
writeBack: {
|
85
|
+
events: ["change", "input", "keyup"]
|
86
|
+
},
|
87
|
+
|
88
|
+
reportValidity: {
|
89
|
+
selector: "input,select,textarea",
|
90
|
+
}
|
91
|
+
|
92
|
+
}
|
93
|
+
);
|
94
|
+
|
95
|
+
obj['features']['mutationObserver'] = false;
|
96
|
+
obj['features']['writeBack'] = true;
|
97
|
+
|
98
|
+
return obj;
|
99
|
+
|
100
|
+
}
|
101
|
+
|
102
|
+
|
103
|
+
/**
|
104
|
+
*
|
105
|
+
* @return {string}
|
106
|
+
*/
|
107
|
+
static getTag() {
|
108
|
+
return "monster-form";
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* @return {CSSStyleSheet[]}
|
113
|
+
*/
|
114
|
+
static getCSSStyleSheet() {
|
115
|
+
return [FormStyleSheet];
|
116
|
+
}
|
117
|
+
|
118
|
+
/**
|
119
|
+
*
|
120
|
+
*/
|
121
|
+
[assembleMethodSymbol]() {
|
122
|
+
super[assembleMethodSymbol]();
|
123
|
+
|
124
|
+
initControlReferences.call(this);
|
125
|
+
initEventHandler.call(this);
|
126
|
+
initDataSourceHandler.call(this);
|
127
|
+
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* This method is called when the component is created.
|
132
|
+
* @since 3.70.0
|
133
|
+
* @returns {DataSet}
|
134
|
+
*/
|
135
|
+
refresh() {
|
136
|
+
this.write();
|
137
|
+
super.refresh();
|
138
|
+
return this;
|
139
|
+
}
|
140
|
+
|
141
|
+
/**
|
142
|
+
* Run reportValidation on all child html form controls.
|
143
|
+
*
|
144
|
+
* @since 2.10.0
|
145
|
+
* @returns {boolean}
|
146
|
+
*/
|
147
|
+
reportValidity() {
|
148
|
+
let valid = true;
|
149
|
+
|
150
|
+
const selector = this.getOption("reportValidity.selector");
|
151
|
+
const nodes = getSlottedElements.call(this, selector);
|
152
|
+
|
153
|
+
nodes.forEach((node) => {
|
154
|
+
if (typeof node.reportValidity === "function") {
|
155
|
+
if (node.reportValidity() === false) {
|
156
|
+
valid = false;
|
157
|
+
}
|
158
|
+
}
|
159
|
+
});
|
160
|
+
|
161
|
+
return valid;
|
162
|
+
}
|
339
163
|
|
340
|
-
/**
|
341
|
-
* @private
|
342
|
-
*/
|
343
|
-
function initUpdater() {
|
344
|
-
if (!this.shadowRoot) {
|
345
|
-
throw new Error("no shadow-root is defined");
|
346
|
-
}
|
347
|
-
|
348
|
-
const slots = this.shadowRoot.querySelectorAll("slot");
|
349
|
-
for (const [, slot] of Object.entries(slots)) {
|
350
|
-
for (const [, node] of Object.entries(slot.assignedNodes())) {
|
351
|
-
if (!(node instanceof HTMLElement)) {
|
352
|
-
continue;
|
353
|
-
}
|
354
|
-
|
355
|
-
const query = `[${ATTRIBUTE_UPDATER_ATTRIBUTES}],[${ATTRIBUTE_UPDATER_REPLACE}],[${ATTRIBUTE_UPDATER_REMOVE}],[${ATTRIBUTE_UPDATER_INSERT}]`;
|
356
|
-
const controls = node.querySelectorAll(query);
|
357
|
-
|
358
|
-
const list = new Set([...controls]);
|
359
|
-
|
360
|
-
if (node.matches(query)) {
|
361
|
-
list.add(node);
|
362
|
-
}
|
363
|
-
|
364
|
-
if (list.size === 0) {
|
365
|
-
continue;
|
366
|
-
}
|
367
|
-
|
368
|
-
addObjectWithUpdaterToElement.call(
|
369
|
-
node,
|
370
|
-
list,
|
371
|
-
formDataUpdaterSymbol,
|
372
|
-
this[formDataSymbol],
|
373
|
-
);
|
374
|
-
}
|
375
|
-
}
|
376
164
|
}
|
377
165
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
const slots = this.shadowRoot.querySelectorAll("slot");
|
387
|
-
for (const [, slot] of Object.entries(slots)) {
|
388
|
-
for (const [, node] of Object.entries(slot.assignedNodes())) {
|
389
|
-
if (!(node instanceof HTMLElement)) {
|
390
|
-
continue;
|
391
|
-
}
|
392
|
-
|
393
|
-
const query = `[${ATTRIBUTE_FORM_DATASOURCE_ACTION}=write]`;
|
394
|
-
const controls = node.querySelectorAll(query);
|
395
|
-
|
396
|
-
const list = new Set([...controls]);
|
397
|
-
|
398
|
-
if (node.matches(query)) {
|
399
|
-
list.add(node);
|
400
|
-
}
|
401
|
-
|
402
|
-
if (list.size === 0) {
|
403
|
-
continue;
|
404
|
-
}
|
405
|
-
|
406
|
-
initWriteActions.call(this, list);
|
407
|
-
}
|
408
|
-
}
|
409
|
-
}
|
166
|
+
function initDataSourceHandler() {
|
167
|
+
if (!this[datasourceLinkedElementSymbol]) {
|
168
|
+
return;
|
169
|
+
}
|
170
|
+
console.log(this[datasourceLinkedElementSymbol]);
|
171
|
+
this[datasourceLinkedElementSymbol].setOption("write.responseCallback", (response) => {
|
172
|
+
console.log("response!!!", response);
|
173
|
+
})
|
410
174
|
|
411
|
-
/**
|
412
|
-
* @private
|
413
|
-
* @param elements
|
414
|
-
*/
|
415
|
-
function initWriteActions(elements) {
|
416
|
-
elements.forEach((element) => {
|
417
|
-
if (element instanceof HTMLElement) {
|
418
|
-
element.addEventListener("click", () => {
|
419
|
-
runWriteCallback.call(this, element);
|
420
|
-
});
|
421
|
-
|
422
|
-
const g = element?.getOption;
|
423
|
-
if (!isFunction(g)) {
|
424
|
-
return;
|
425
|
-
}
|
426
|
-
|
427
|
-
const s = element?.setOption;
|
428
|
-
if (!isFunction(s)) {
|
429
|
-
return;
|
430
|
-
}
|
431
|
-
|
432
|
-
const fn = element.getOption("actions.click");
|
433
|
-
|
434
|
-
if (!isFunction(fn)) {
|
435
|
-
return;
|
436
|
-
}
|
437
|
-
|
438
|
-
// disable console.log of standard click event
|
439
|
-
element.setOption("actions.click", function () {
|
440
|
-
// do nothing!
|
441
|
-
});
|
442
|
-
}
|
443
|
-
});
|
444
|
-
}
|
445
|
-
|
446
|
-
function runWriteCallback(button) {
|
447
|
-
if (typeof this.reportValidity === "function") {
|
448
|
-
if (this.reportValidity() === false) {
|
449
|
-
if (
|
450
|
-
button instanceof StateButton ||
|
451
|
-
button instanceof MessageStateButton
|
452
|
-
) {
|
453
|
-
button.setState("failed");
|
454
|
-
}
|
455
|
-
return;
|
456
|
-
}
|
457
|
-
}
|
458
|
-
|
459
|
-
const datasource = this.getOption("datasource");
|
460
|
-
if (!(datasource instanceof Datasource)) {
|
461
|
-
return;
|
462
|
-
}
|
463
|
-
|
464
|
-
if (button instanceof StateButton || button instanceof MessageStateButton) {
|
465
|
-
button.setState("activity");
|
466
|
-
}
|
467
|
-
|
468
|
-
//const data = form?.[formDataSymbol]?.getRealSubject();
|
469
|
-
const writePromise = datasource
|
470
|
-
.set(this[formDataSymbol].getRealSubject())
|
471
|
-
.write();
|
472
|
-
if (!(writePromise instanceof Promise)) {
|
473
|
-
throw new Error("datasource.write() must return a promise");
|
474
|
-
}
|
475
|
-
|
476
|
-
writePromise
|
477
|
-
.then((r) => {
|
478
|
-
if (
|
479
|
-
button instanceof StateButton ||
|
480
|
-
button instanceof MessageStateButton
|
481
|
-
) {
|
482
|
-
button.setState("successful");
|
483
|
-
}
|
484
|
-
this[formDataSymbol].getSubject()[PROPERTY_VALIDATION_KEY] = {};
|
485
|
-
})
|
486
|
-
.catch((e) => {
|
487
|
-
if (e instanceof WriteError) {
|
488
|
-
this[formDataSymbol].getSubject()[PROPERTY_VALIDATION_KEY] =
|
489
|
-
e.getValidation();
|
490
|
-
}
|
491
|
-
|
492
|
-
if (
|
493
|
-
button instanceof StateButton ||
|
494
|
-
button instanceof MessageStateButton
|
495
|
-
) {
|
496
|
-
button.setState("failed");
|
497
|
-
}
|
498
|
-
|
499
|
-
if (button instanceof MessageStateButton) {
|
500
|
-
button.setMessage(e.message);
|
501
|
-
button.showMessage();
|
502
|
-
}
|
503
|
-
});
|
504
|
-
}
|
505
|
-
|
506
|
-
/**
|
507
|
-
* This attribute can be used to pass a URL to this select.
|
508
|
-
*
|
509
|
-
* ```
|
510
|
-
* <monster-form data-monster-datasource="restapi:....."></monster-form>
|
511
|
-
* ```
|
512
|
-
*
|
513
|
-
* @private
|
514
|
-
* @return {object}
|
515
|
-
*/
|
516
|
-
function initOptionsFromArguments() {
|
517
|
-
const options = {};
|
518
|
-
|
519
|
-
const datasource = this.getAttribute(ATTRIBUTE_FORM_DATASOURCE);
|
520
|
-
if (isString(datasource)) {
|
521
|
-
for (const [key, classObject] of Form.getDatasources()) {
|
522
|
-
if (datasource === key) {
|
523
|
-
let args = this.getAttribute(ATTRIBUTE_FORM_DATASOURCE_ARGUMENTS);
|
524
|
-
|
525
|
-
try {
|
526
|
-
args = JSON.parse(args);
|
527
|
-
} catch (e) {
|
528
|
-
this.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.toString());
|
529
|
-
continue;
|
530
|
-
}
|
531
|
-
|
532
|
-
try {
|
533
|
-
options["datasource"] = new classObject(args);
|
534
|
-
} catch (e) {
|
535
|
-
this.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.toString());
|
536
|
-
continue;
|
537
|
-
}
|
538
|
-
|
539
|
-
break;
|
540
|
-
}
|
541
|
-
|
542
|
-
if (options["datasource"] instanceof Datasource) {
|
543
|
-
break;
|
544
|
-
}
|
545
|
-
}
|
546
|
-
}
|
547
|
-
|
548
|
-
return options;
|
549
175
|
}
|
550
176
|
|
551
177
|
/**
|
552
178
|
* @private
|
553
|
-
* @
|
179
|
+
* @returns {initEventHandler}
|
554
180
|
*/
|
555
|
-
function
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
181
|
+
function initEventHandler() {
|
182
|
+
|
183
|
+
if (this.getOption("features.writeBack") === true) {
|
184
|
+
const events = this.getOption("writeBack.events");
|
185
|
+
for (const event of events) {
|
186
|
+
|
187
|
+
this.addEventListener(event, (e) => {
|
188
|
+
|
189
|
+
if (!this.reportValidity()) {
|
190
|
+
|
191
|
+
this.classList.add("invalid");
|
192
|
+
setTimeout(() => {
|
193
|
+
this.classList.remove("invalid");
|
194
|
+
}, 1000)
|
195
|
+
|
196
|
+
return;
|
197
|
+
}
|
198
|
+
|
199
|
+
if (this[debounceCallbackSymbol] instanceof DeadMansSwitch) {
|
200
|
+
try {
|
201
|
+
this[debounceCallbackSymbol].touch();
|
202
|
+
return;
|
203
|
+
} catch (e) {
|
204
|
+
if (e.message !== "has already run") {
|
205
|
+
throw e;
|
206
|
+
}
|
207
|
+
delete this[debounceCallbackSymbol];
|
208
|
+
}
|
209
|
+
}
|
210
|
+
|
211
|
+
this[debounceCallbackSymbol] = new DeadMansSwitch(200, () => {
|
212
|
+
setTimeout(() => {
|
213
|
+
this.write();
|
214
|
+
}, 0);
|
215
|
+
});
|
216
|
+
|
217
|
+
});
|
218
|
+
}
|
219
|
+
}
|
220
|
+
|
221
|
+
return this;
|
571
222
|
}
|
572
223
|
|
573
224
|
/**
|
574
225
|
* @private
|
575
|
-
* @return {
|
226
|
+
* @return {FilterButton}
|
576
227
|
*/
|
577
228
|
function initControlReferences() {
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
this[formElementSymbol] = this.shadowRoot.querySelector(
|
583
|
-
"[data-monster-role=form]",
|
584
|
-
);
|
585
|
-
return this;
|
229
|
+
if (!this.shadowRoot) {
|
230
|
+
throw new Error("no shadow-root is defined");
|
231
|
+
}
|
232
|
+
return this;
|
586
233
|
}
|
587
234
|
|
588
235
|
/**
|
@@ -590,8 +237,8 @@ function initControlReferences() {
|
|
590
237
|
* @return {string}
|
591
238
|
*/
|
592
239
|
function getTemplate() {
|
593
|
-
|
594
|
-
|
240
|
+
// language=HTML
|
241
|
+
return `
|
595
242
|
<div data-monster-role="control" part="control">
|
596
243
|
<form data-monster-attributes="disabled path:disabled | if:true, class path:classes.form"
|
597
244
|
data-monster-role="form"
|