@jinntec/fore 1.1.0 → 1.3.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/dist/fore-dev.js +8 -8
- package/dist/fore-dev.js.map +1 -1
- package/dist/fore.js +7 -7
- package/dist/fore.js.map +1 -1
- package/index.js +1 -0
- package/package.json +2 -2
- package/resources/fore.css +95 -72
- package/src/ForeElementMixin.js +1 -1
- package/src/actions/abstract-action.js +55 -7
- package/src/actions/fx-action.js +2 -2
- package/src/actions/fx-confirm.js +2 -2
- package/src/actions/fx-delete.js +53 -62
- package/src/actions/fx-hide.js +3 -1
- package/src/actions/fx-message.js +25 -1
- package/src/actions/fx-refresh.js +9 -0
- package/src/actions/fx-reload.js +30 -0
- package/src/actions/fx-replace.js +1 -0
- package/src/actions/fx-send.js +11 -1
- package/src/actions/fx-setfocus.js +32 -5
- package/src/actions/fx-setvalue.js +4 -4
- package/src/actions/fx-show.js +1 -0
- package/src/actions/fx-toggle.js +5 -0
- package/src/events.js +24 -0
- package/src/fore.js +71 -8
- package/src/fx-bind.js +2 -2
- package/src/fx-fore.js +71 -20
- package/src/fx-instance.js +33 -8
- package/src/fx-model.js +435 -444
- package/src/fx-submission.js +78 -65
- package/src/getInScopeContext.js +91 -83
- package/src/modelitem.js +2 -2
- package/src/relevance.js +1 -1
- package/src/ui/abstract-control.js +114 -27
- package/src/ui/fx-alert.js +0 -1
- package/src/ui/fx-container.js +23 -27
- package/src/ui/fx-control.js +90 -34
- package/src/ui/fx-group.js +5 -0
- package/src/ui/fx-inspector.js +5 -2
- package/src/ui/fx-output.js +17 -15
- package/src/ui/fx-repeat.js +2 -2
- package/src/ui/fx-repeatitem.js +5 -3
- package/src/ui/fx-switch.js +11 -7
- package/src/ui/fx-trigger.js +15 -9
- package/src/xpath-evaluation.js +31 -18
- package/src/xpath-util.js +13 -0
package/src/fx-submission.js
CHANGED
|
@@ -72,7 +72,7 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
async _submit() {
|
|
75
|
-
console.log('submitting....');
|
|
75
|
+
console.log('submitting....', this.getAttribute('id'));
|
|
76
76
|
this.evalInContext();
|
|
77
77
|
const model = this.getModel();
|
|
78
78
|
|
|
@@ -81,11 +81,12 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
81
81
|
if (this.validate==='true') {
|
|
82
82
|
const valid = model.revalidate();
|
|
83
83
|
if (!valid) {
|
|
84
|
-
console.log('validation failed.
|
|
84
|
+
console.log('validation failed. Submission stopped');
|
|
85
|
+
this.getOwnerForm().classList.add('submit-validation-failed');
|
|
85
86
|
// ### allow alerts to pop up
|
|
86
87
|
// this.dispatch('submit-error', {});
|
|
87
88
|
Fore.dispatch(this, 'submit-error', {});
|
|
88
|
-
this.getModel().parentNode.refresh();
|
|
89
|
+
this.getModel().parentNode.refresh(true);
|
|
89
90
|
return;
|
|
90
91
|
}
|
|
91
92
|
}
|
|
@@ -152,29 +153,39 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
152
153
|
return;
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
if(resolvedUrl.startsWith('localStore:')
|
|
156
|
-
// let data = this._parse(serialized, instance);
|
|
157
|
-
const key = resolvedUrl.substring(resolvedUrl.indexOf(':')+1);
|
|
158
|
-
localStorage.setItem(key,serialized);
|
|
159
|
-
Fore.dispatch(this, 'submit-done', {});
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
156
|
+
if(resolvedUrl.startsWith('localStore:')){
|
|
162
157
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
158
|
+
if(this.method === 'get' || this.method === 'consume'){
|
|
159
|
+
// let data = this._parse(serialized, instance);
|
|
160
|
+
this.replace = 'instance';
|
|
161
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':')+1);
|
|
162
|
+
const serialized = localStorage.getItem(key);
|
|
163
|
+
if(!serialized){
|
|
164
|
+
Fore.dispatch(this, 'submit-error', { message: `Error reading key ${key} from localstorage` });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
let data = this._parse(serialized, instance);
|
|
168
|
+
this._handleResponse(data);
|
|
169
|
+
if(this.method === 'consume'){
|
|
170
|
+
localStorage.removeItem(key);
|
|
171
|
+
}
|
|
172
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
171
173
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
174
|
+
if(this.method === 'post'){
|
|
175
|
+
// let data = this._parse(serialized, instance);
|
|
176
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':')+1);
|
|
177
|
+
localStorage.setItem(key,serialized);
|
|
178
|
+
this._handleResponse(instance.instanceData);
|
|
179
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
180
|
+
}
|
|
181
|
+
if(this.method === 'delete'){
|
|
182
|
+
const key = resolvedUrl.substring(resolvedUrl.indexOf(':')+1);
|
|
175
183
|
localStorage.removeItem(key);
|
|
184
|
+
const newInst = new DOMParser().parseFromString('<data></data>', 'application/xml');
|
|
185
|
+
this._handleResponse(newInst);
|
|
186
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
176
187
|
}
|
|
177
|
-
|
|
188
|
+
|
|
178
189
|
return;
|
|
179
190
|
}
|
|
180
191
|
|
|
@@ -182,52 +193,51 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
182
193
|
const headers = this._getHeaders();
|
|
183
194
|
console.log('headers', headers);
|
|
184
195
|
|
|
185
|
-
// ### map urlencoded-post to post for fetch
|
|
186
|
-
if (this.method === 'urlencoded-post') {
|
|
187
|
-
this.method = 'post';
|
|
188
|
-
}
|
|
189
|
-
|
|
190
196
|
if (!this.methods.includes(this.method.toLowerCase())) {
|
|
191
197
|
// this.dispatch('error', { message: `Unknown method ${this.method}` });
|
|
192
198
|
Fore.dispatch(this, 'error', { message: `Unknown method ${this.method}` });
|
|
193
199
|
return;
|
|
194
200
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
201
|
+
try{
|
|
202
|
+
const response = await fetch(resolvedUrl, {
|
|
203
|
+
method: this.method,
|
|
204
|
+
mode: 'cors',
|
|
205
|
+
credentials: 'include',
|
|
206
|
+
headers,
|
|
207
|
+
body: serialized,
|
|
208
|
+
});
|
|
202
209
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
210
|
+
if (!response.ok || response.status > 400) {
|
|
211
|
+
// this.dispatch('submit-error', { message: `Error while submitting ${this.id}` });
|
|
212
|
+
Fore.dispatch(this, 'submit-error', { message: `Error while submitting ${this.id}` });
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
208
215
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
216
|
+
const contentType = response.headers.get('content-type').toLowerCase();
|
|
217
|
+
if (
|
|
218
|
+
contentType.startsWith('text/plain') ||
|
|
219
|
+
contentType.startsWith('text/html') ||
|
|
220
|
+
contentType.startsWith('text/markdown')
|
|
221
|
+
) {
|
|
222
|
+
const text = await response.text();
|
|
223
|
+
this._handleResponse(text);
|
|
224
|
+
} else if (contentType.startsWith('application/json')) {
|
|
225
|
+
const json = await response.json();
|
|
226
|
+
this._handleResponse(json);
|
|
227
|
+
} else if (contentType.startsWith('application/xml')) {
|
|
228
|
+
const text = await response.text();
|
|
229
|
+
const xml = new DOMParser().parseFromString(text, 'application/xml');
|
|
230
|
+
this._handleResponse(xml);
|
|
231
|
+
} else {
|
|
232
|
+
const blob = await response.blob();
|
|
233
|
+
this._handleResponse(blob);
|
|
234
|
+
}
|
|
228
235
|
|
|
229
|
-
|
|
230
|
-
|
|
236
|
+
// this.dispatch('submit-done', {});
|
|
237
|
+
Fore.dispatch(this, 'submit-done', {});
|
|
238
|
+
} catch (error){
|
|
239
|
+
Fore.dispatch(this, 'submit-error', {error:error.message});
|
|
240
|
+
}
|
|
231
241
|
}
|
|
232
242
|
|
|
233
243
|
_parse(serialized, instance) {
|
|
@@ -242,7 +252,7 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
242
252
|
}
|
|
243
253
|
|
|
244
254
|
_serialize(instanceType, relevantNodes) {
|
|
245
|
-
if (this.
|
|
255
|
+
if (this.serialization === 'application/x-www-form-urlencoded') {
|
|
246
256
|
// this.method = 'post';
|
|
247
257
|
const params = new URLSearchParams();
|
|
248
258
|
// console.log('nodes to serialize', relevantNodes);
|
|
@@ -267,7 +277,7 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
267
277
|
|
|
268
278
|
// ### set content-type header according to type of instance
|
|
269
279
|
const instance = this.getInstance();
|
|
270
|
-
const contentType = Fore.getContentType(instance, this.
|
|
280
|
+
const contentType = Fore.getContentType(instance, this.serialization);
|
|
271
281
|
headers.append('Content-Type', contentType);
|
|
272
282
|
// ### needed to overwrite browsers' setting of 'Accept' header
|
|
273
283
|
if (headers.has('Accept')) {
|
|
@@ -340,7 +350,11 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
340
350
|
this,
|
|
341
351
|
);
|
|
342
352
|
console.log('theTarget', theTarget);
|
|
343
|
-
|
|
353
|
+
if(data.nodeType === Node.DOCUMENT_NODE){
|
|
354
|
+
theTarget.appendChild( data.firstElementChild);
|
|
355
|
+
}else{
|
|
356
|
+
theTarget.innerHTML = data;
|
|
357
|
+
}
|
|
344
358
|
} else {
|
|
345
359
|
const instanceData = data;
|
|
346
360
|
targetInstance.instanceData = instanceData;
|
|
@@ -349,8 +363,7 @@ export class FxSubmission extends foreElementMixin(HTMLElement) {
|
|
|
349
363
|
}
|
|
350
364
|
|
|
351
365
|
this.model.updateModel(); // force update
|
|
352
|
-
|
|
353
|
-
this.getOwnerForm().refresh();
|
|
366
|
+
this.getOwnerForm().refresh(true);
|
|
354
367
|
} else {
|
|
355
368
|
throw new Error(`target instance not found: ${targetInstance}`);
|
|
356
369
|
}
|
package/src/getInScopeContext.js
CHANGED
|
@@ -1,106 +1,114 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {evaluateXPathToFirstNode} from './xpath-evaluation.js';
|
|
2
|
+
import {Fore} from './fore.js';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {XPathUtil} from './xpath-util.js';
|
|
5
5
|
|
|
6
6
|
function _getElement(node) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
if (node && node.nodeType && node.nodeType === Node.ATTRIBUTE_NODE) {
|
|
8
|
+
// The context of an attribute is the ref of the element it's defined on
|
|
9
|
+
return node.ownerElement;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
13
|
+
// The context of a query should be the element having a ref
|
|
14
|
+
return node;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// For text nodes, just start looking from the parent element
|
|
18
|
+
return node.parentNode;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function _getForeContext(node) {
|
|
22
|
-
|
|
22
|
+
return node.closest('fx-fore');
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
function _getModelInContext(node) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
// const ownerForm = node.closest('fx-fore');
|
|
27
|
+
const ownerForm = _getForeContext(node);
|
|
28
|
+
return ownerForm.getModel();
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
function _getInitialContext(node, ref) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
const parentBind = Fore.getClosest('[ref]', node);
|
|
33
|
+
const localFore = Fore.getClosest('fx-fore', node);
|
|
34
|
+
|
|
35
|
+
const model = _getModelInContext(node);
|
|
36
|
+
|
|
37
|
+
if (parentBind !== null) {
|
|
38
|
+
/*
|
|
39
|
+
make sure that the closest ref belongs to the same fx-fore element
|
|
40
|
+
*/
|
|
41
|
+
const parentBindFore = parentBind.closest('fx-fore');
|
|
42
|
+
if (localFore === parentBindFore) {
|
|
43
|
+
return parentBind.nodeset;
|
|
44
|
+
}
|
|
45
|
+
return model.getDefaultInstance().getDefaultContext();
|
|
44
46
|
}
|
|
45
|
-
return model.getDefaultInstance().getDefaultContext();
|
|
46
|
-
}
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
if (XPathUtil.isAbsolutePath(ref)) {
|
|
49
|
+
const instanceId = XPathUtil.getInstanceId(ref);
|
|
50
|
+
if (instanceId) {
|
|
51
|
+
return model.getInstance(instanceId).getDefaultContext();
|
|
52
|
+
}
|
|
53
|
+
return model.getDefaultInstance().getDefaultContext();
|
|
54
|
+
}
|
|
55
|
+
if (model.getDefaultInstance() !== null && model.inited) {
|
|
56
|
+
return model.getDefaultInstance().getDefaultContext();
|
|
52
57
|
}
|
|
53
|
-
return
|
|
54
|
-
}
|
|
55
|
-
if (model.getDefaultInstance() !== null && model.inited) {
|
|
56
|
-
return model.getDefaultInstance().getDefaultContext();
|
|
57
|
-
}
|
|
58
|
-
return [];
|
|
58
|
+
return [];
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
export default function getInScopeContext(node, ref) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (node.nodeName === 'context') {
|
|
67
|
-
return evaluateXPathToFirstNode(
|
|
68
|
-
node.nodeValue,
|
|
69
|
-
repeatItem.nodeset,
|
|
70
|
-
_getForeContext(parentElement),
|
|
71
|
-
);
|
|
62
|
+
const parentElement = _getElement(node);
|
|
63
|
+
|
|
64
|
+
if(parentElement.nodeName === 'FX-FORE'){
|
|
65
|
+
return parentElement.getModel().getDefaultInstance().getDefaultContext();
|
|
72
66
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (parentElement.hasAttribute('context')) {
|
|
77
|
-
const initialContext = _getInitialContext(parentElement.parentNode, ref);
|
|
78
|
-
const contextAttr = parentElement.getAttribute('context');
|
|
79
|
-
return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (node.nodeType === Node.ATTRIBUTE_NODE && node.nodeName === 'context') {
|
|
83
|
-
const initialContext = _getInitialContext(node.ownerElement.parentNode, ref);
|
|
84
|
-
const contextAttr = node.ownerElement.getAttribute('context');
|
|
85
|
-
return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
|
|
86
|
-
}
|
|
87
|
-
if (node.nodeType === Node.ATTRIBUTE_NODE && node.nodeName === 'ref') {
|
|
88
|
-
// Note: do not consider the ref of the owner element since it should not be used to define the
|
|
89
|
-
// context
|
|
90
|
-
if (node.ownerElement.hasAttribute('context')) {
|
|
91
|
-
const initialContext = _getInitialContext(node.ownerElement.parentNode, ref);
|
|
92
|
-
const contextAttr = node.ownerElement.getAttribute('context');
|
|
93
|
-
return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
|
|
67
|
+
const parentBind = Fore.getClosest('[ref]', parentElement.parentNode);
|
|
68
|
+
if (parentBind && parentBind.nodeName === 'FX-GROUP') {
|
|
69
|
+
return parentBind.nodeset;
|
|
94
70
|
}
|
|
95
71
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
72
|
+
const repeatItem = Fore.getClosest('fx-repeatitem', parentElement);
|
|
73
|
+
if (repeatItem) {
|
|
74
|
+
if (node.nodeName === 'context') {
|
|
75
|
+
return evaluateXPathToFirstNode(
|
|
76
|
+
node.nodeValue,
|
|
77
|
+
repeatItem.nodeset,
|
|
78
|
+
_getForeContext(parentElement),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
return repeatItem.nodeset;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (parentElement.hasAttribute('context')) {
|
|
85
|
+
const initialContext = _getInitialContext(parentElement.parentNode, ref);
|
|
86
|
+
const contextAttr = parentElement.getAttribute('context');
|
|
87
|
+
return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (node.nodeType === Node.ATTRIBUTE_NODE && node.nodeName === 'context') {
|
|
91
|
+
const initialContext = _getInitialContext(node.ownerElement.parentNode, ref);
|
|
92
|
+
const contextAttr = node.ownerElement.getAttribute('context');
|
|
93
|
+
return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
|
|
94
|
+
}
|
|
95
|
+
if (node.nodeType === Node.ATTRIBUTE_NODE && node.nodeName === 'ref') {
|
|
96
|
+
// Note: do not consider the ref of the owner element since it should not be used to define the
|
|
97
|
+
// context
|
|
98
|
+
if (node.ownerElement.hasAttribute('context')) {
|
|
99
|
+
const initialContext = _getInitialContext(node.ownerElement.parentNode, ref);
|
|
100
|
+
const contextAttr = node.ownerElement.getAttribute('context');
|
|
101
|
+
return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Never resolve the context from a ref itself!
|
|
105
|
+
return _getInitialContext(parentElement.parentNode, ref);
|
|
106
|
+
}
|
|
99
107
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
// if (node.nodeType === Node.ELEMENT_NODE && node.hasAttribute('context')) {
|
|
109
|
+
// const initialContext = _getInitialContext(node.parentNode, ref);
|
|
110
|
+
// const contextAttr = node.getAttribute('context');
|
|
111
|
+
// return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
|
|
112
|
+
// }
|
|
113
|
+
return _getInitialContext(parentElement, ref);
|
|
106
114
|
}
|
package/src/modelitem.js
CHANGED
|
@@ -50,8 +50,8 @@ export class ModelItem {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
set value(newVal) {
|
|
53
|
-
console.log('modelitem.setvalue oldVal', this.value);
|
|
54
|
-
console.log('modelitem.setvalue newVal', newVal);
|
|
53
|
+
// console.log('modelitem.setvalue oldVal', this.value);
|
|
54
|
+
// console.log('modelitem.setvalue newVal', newVal);
|
|
55
55
|
|
|
56
56
|
if (newVal.nodeType === Node.DOCUMENT_NODE) {
|
|
57
57
|
this.node.replaceWith(newVal.firstElementChild);
|
package/src/relevance.js
CHANGED
|
@@ -16,9 +16,32 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
16
16
|
this.required = false;
|
|
17
17
|
this.readonly = false;
|
|
18
18
|
this.widget = null;
|
|
19
|
+
this.visited = false;
|
|
20
|
+
this.force = false;
|
|
19
21
|
// this.attachShadow({ mode: 'open' });
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
|
|
25
|
+
// todo: discuss - this is a hack to circumvent that modelItems in toRefresh diverge from the modelItems in
|
|
26
|
+
// the model in some situations. This code first looks for refresh
|
|
27
|
+
/*
|
|
28
|
+
getModelItem() {
|
|
29
|
+
console.log('toRefreshModelItems', this.getOwnerForm().toRefresh);
|
|
30
|
+
const s = this.modelItem.path;
|
|
31
|
+
console.log('toRefreshModelItems path', s);
|
|
32
|
+
|
|
33
|
+
const toRefresh = this.getOwnerForm().toRefresh;
|
|
34
|
+
let mi;
|
|
35
|
+
if(toRefresh){
|
|
36
|
+
mi = this.getOwnerForm().toRefresh.find(m => m.path === s);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return mi? mi: super.getModelItem();
|
|
40
|
+
// console.log('toRefreshModelItems realitem', mi);
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
*/
|
|
44
|
+
|
|
22
45
|
// eslint-disable-next-line class-methods-use-this
|
|
23
46
|
getWidget() {
|
|
24
47
|
throw new Error('You have to implement the method getWidget!');
|
|
@@ -27,7 +50,8 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
27
50
|
/**
|
|
28
51
|
* (re)apply all modelItem state properties to this control. model -> UI
|
|
29
52
|
*/
|
|
30
|
-
async refresh() {
|
|
53
|
+
async refresh(force) {
|
|
54
|
+
if(force) this.force=true;
|
|
31
55
|
// console.log('### AbstractControl.refresh on : ', this);
|
|
32
56
|
|
|
33
57
|
const currentVal = this.value;
|
|
@@ -40,22 +64,25 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
40
64
|
this.oldVal = this.nodeset ? this.nodeset : null;
|
|
41
65
|
this.evalInContext();
|
|
42
66
|
|
|
67
|
+
// todo this if should be removed - see above
|
|
43
68
|
if (this.isBound()) {
|
|
44
69
|
// this.control = this.querySelector('#control');
|
|
45
70
|
|
|
46
|
-
if
|
|
71
|
+
if(!this.nodeset){
|
|
47
72
|
this.style.display = 'none';
|
|
48
73
|
return;
|
|
49
74
|
}
|
|
50
75
|
|
|
51
76
|
this.modelItem = this.getModelItem();
|
|
77
|
+
// console.log('refresh modelItem', this.modelItem);
|
|
52
78
|
|
|
53
79
|
if (this.modelItem instanceof ModelItem) {
|
|
54
80
|
// console.log('### XfAbstractControl.refresh modelItem : ', this.modelItem);
|
|
55
81
|
|
|
56
82
|
if (this.hasAttribute('as') && this.getAttribute('as') === 'node') {
|
|
57
|
-
console.log('as', this.nodeset);
|
|
58
|
-
this.modelItem.value = this.nodeset;
|
|
83
|
+
// console.log('as', this.nodeset);
|
|
84
|
+
// this.modelItem.value = this.nodeset;
|
|
85
|
+
this.modelItem.node = this.nodeset;
|
|
59
86
|
this.value = this.modelItem.node;
|
|
60
87
|
} else {
|
|
61
88
|
this.value = this.modelItem.value;
|
|
@@ -93,13 +120,19 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
93
120
|
|
|
94
121
|
// if(!this.closest('fx-fore').ready) return; // state change event do not fire during init phase (initial refresh)
|
|
95
122
|
if (!this.getOwnerForm().ready) return; // state change event do not fire during init phase (initial refresh)
|
|
96
|
-
if (currentVal !== this.value) {
|
|
97
|
-
|
|
123
|
+
if (currentVal !== this.value ) {
|
|
124
|
+
// todo: discuss how to prevent unnecessary/unwanted value-changes e.g. when repeatitems are inserted
|
|
125
|
+
// if (currentVal !== this.value && this.visited) {
|
|
126
|
+
Fore.dispatch(this, 'value-changed', { path: this.modelItem.path , value:this.modelItem.value});
|
|
98
127
|
}
|
|
99
128
|
}
|
|
100
129
|
}
|
|
101
130
|
}
|
|
102
131
|
|
|
132
|
+
refreshFromModelItem(modelItem){
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
103
136
|
/**
|
|
104
137
|
*
|
|
105
138
|
* @returns {Promise<void>}
|
|
@@ -134,25 +167,72 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
134
167
|
handleRequired() {
|
|
135
168
|
// console.log('mip required', this.modelItem.required);
|
|
136
169
|
this.widget = this.getWidget();
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
this.classList.add('isRequiredFalse');
|
|
143
|
-
}else{
|
|
144
|
-
this.classList.remove('isRequiredFalse');
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
this.widget.setAttribute('required', '');
|
|
148
|
-
this.setAttribute('required', '');
|
|
149
|
-
this._dispatchEvent('required');
|
|
150
|
-
} else {
|
|
151
|
-
this.widget.removeAttribute('required');
|
|
152
|
-
this.removeAttribute('required');
|
|
170
|
+
|
|
171
|
+
if(!this.modelItem.required){
|
|
172
|
+
this.widget.removeAttribute('required');
|
|
173
|
+
this.removeAttribute('required');
|
|
174
|
+
if (this.isRequired() !== this.modelItem.required){
|
|
153
175
|
this._dispatchEvent('optional');
|
|
154
176
|
}
|
|
155
|
-
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ### modelItem is required
|
|
181
|
+
if (this.visited || this.force) {
|
|
182
|
+
if (this.modelItem.value === '') {
|
|
183
|
+
this.classList.add('isEmpty');
|
|
184
|
+
this._toggleValid(false);
|
|
185
|
+
} else {
|
|
186
|
+
this.classList.remove('isEmpty');
|
|
187
|
+
this._toggleValid(true);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
this.widget.setAttribute('required', '');
|
|
191
|
+
this.setAttribute('required', '');
|
|
192
|
+
if (this.isRequired() !== this.modelItem.required) {
|
|
193
|
+
this._dispatchEvent('required');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
if (this.isRequired() !== this.modelItem.required) {
|
|
198
|
+
this._updateRequired();
|
|
199
|
+
}
|
|
200
|
+
*/
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
_updateRequired() {
|
|
205
|
+
if (this.modelItem.required) {
|
|
206
|
+
// if (this.getOwnerForm().ready){
|
|
207
|
+
if (this.visited || this.force) {
|
|
208
|
+
// if (this.visited ) {
|
|
209
|
+
// if (this.widget.value === '') {
|
|
210
|
+
if (this.modelItem.value === '') {
|
|
211
|
+
this.classList.add('isEmpty');
|
|
212
|
+
this._toggleValid(false);
|
|
213
|
+
} else {
|
|
214
|
+
this.classList.remove('isEmpty');
|
|
215
|
+
this._toggleValid(true);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
this.widget.setAttribute('required', '');
|
|
219
|
+
this.setAttribute('required', '');
|
|
220
|
+
this._dispatchEvent('required');
|
|
221
|
+
} else {
|
|
222
|
+
this.widget.removeAttribute('required');
|
|
223
|
+
this.removeAttribute('required');
|
|
224
|
+
this._dispatchEvent('optional');
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
_toggleValid(valid){
|
|
229
|
+
if(valid){
|
|
230
|
+
this.removeAttribute('invalid');
|
|
231
|
+
this.setAttribute('valid','');
|
|
232
|
+
}else{
|
|
233
|
+
this.removeAttribute('valid');
|
|
234
|
+
this.setAttribute('invalid','');
|
|
235
|
+
}
|
|
156
236
|
}
|
|
157
237
|
|
|
158
238
|
handleReadonly() {
|
|
@@ -176,28 +256,35 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
176
256
|
// console.log('mip valid', this.modelItem.required);
|
|
177
257
|
const alert = this.querySelector('fx-alert');
|
|
178
258
|
|
|
259
|
+
const mi = this.getModelItem();
|
|
260
|
+
console.log('late modelItem', mi);
|
|
179
261
|
if (this.isValid() !== this.modelItem.constraint) {
|
|
180
262
|
if (this.modelItem.constraint) {
|
|
181
|
-
if (alert) alert.style.display = 'none';
|
|
263
|
+
// if (alert) alert.style.display = 'none';
|
|
182
264
|
this._dispatchEvent('valid');
|
|
265
|
+
this.setAttribute('valid','');
|
|
183
266
|
this.removeAttribute('invalid');
|
|
184
267
|
} else {
|
|
185
268
|
this.setAttribute('invalid', '');
|
|
269
|
+
this.removeAttribute('valid');
|
|
186
270
|
// ### constraint is invalid - handle alerts
|
|
271
|
+
/*
|
|
187
272
|
if (alert) {
|
|
188
273
|
alert.style.display = 'block';
|
|
189
274
|
}
|
|
275
|
+
*/
|
|
190
276
|
if (this.modelItem.alerts.length !== 0) {
|
|
191
|
-
const { alerts } = this.modelItem;
|
|
192
|
-
console.log('alerts from bind: ', alerts);
|
|
193
277
|
|
|
194
278
|
const controlAlert = this.querySelector('fx-alert');
|
|
195
279
|
if (!controlAlert) {
|
|
280
|
+
const { alerts } = this.modelItem;
|
|
281
|
+
// console.log('alerts from bind: ', alerts);
|
|
196
282
|
alerts.forEach(modelAlert => {
|
|
197
283
|
const newAlert = document.createElement('fx-alert');
|
|
284
|
+
// const newAlert = document.createElement('span');
|
|
198
285
|
newAlert.innerHTML = modelAlert;
|
|
199
286
|
this.appendChild(newAlert);
|
|
200
|
-
newAlert.style.display = 'block';
|
|
287
|
+
// newAlert.style.display = 'block';
|
|
201
288
|
});
|
|
202
289
|
}
|
|
203
290
|
}
|