@jinntec/fore 1.2.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/actions/abstract-action.js +48 -6
- package/src/actions/fx-action.js +1 -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-reload.js +30 -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 +1 -1
- package/src/fx-fore.js +65 -14
- package/src/fx-instance.js +33 -8
- package/src/fx-model.js +435 -441
- package/src/fx-submission.js +76 -62
- package/src/getInScopeContext.js +91 -83
- package/src/modelitem.js +2 -2
- package/src/relevance.js +1 -1
- package/src/ui/abstract-control.js +108 -22
- package/src/ui/fx-alert.js +0 -1
- package/src/ui/fx-container.js +22 -26
- package/src/ui/fx-control.js +84 -34
- package/src/ui/fx-group.js +5 -0
- package/src/ui/fx-inspector.js +5 -0
- package/src/ui/fx-output.js +14 -14
- 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 +28 -17
- package/src/xpath-util.js +13 -0
package/src/fx-submission.js
CHANGED
|
@@ -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;
|
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,6 +64,7 @@ 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
|
|
|
@@ -49,6 +74,7 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
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);
|
|
@@ -94,13 +120,19 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
94
120
|
|
|
95
121
|
// if(!this.closest('fx-fore').ready) return; // state change event do not fire during init phase (initial refresh)
|
|
96
122
|
if (!this.getOwnerForm().ready) return; // state change event do not fire during init phase (initial refresh)
|
|
97
|
-
if (currentVal !== this.value) {
|
|
98
|
-
|
|
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});
|
|
99
127
|
}
|
|
100
128
|
}
|
|
101
129
|
}
|
|
102
130
|
}
|
|
103
131
|
|
|
132
|
+
refreshFromModelItem(modelItem){
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
104
136
|
/**
|
|
105
137
|
*
|
|
106
138
|
* @returns {Promise<void>}
|
|
@@ -135,24 +167,71 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
135
167
|
handleRequired() {
|
|
136
168
|
// console.log('mip required', this.modelItem.required);
|
|
137
169
|
this.widget = this.getWidget();
|
|
138
|
-
|
|
170
|
+
|
|
171
|
+
if(!this.modelItem.required){
|
|
172
|
+
this.widget.removeAttribute('required');
|
|
173
|
+
this.removeAttribute('required');
|
|
174
|
+
if (this.isRequired() !== this.modelItem.required){
|
|
175
|
+
this._dispatchEvent('optional');
|
|
176
|
+
}
|
|
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', '');
|
|
139
192
|
if (this.isRequired() !== this.modelItem.required) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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);
|
|
147
216
|
}
|
|
148
|
-
this.widget.setAttribute('required', '');
|
|
149
|
-
this.setAttribute('required', '');
|
|
150
|
-
this._dispatchEvent('required');
|
|
151
|
-
} else {
|
|
152
|
-
this.widget.removeAttribute('required');
|
|
153
|
-
this.removeAttribute('required');
|
|
154
|
-
this._dispatchEvent('optional');
|
|
155
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','');
|
|
156
235
|
}
|
|
157
236
|
}
|
|
158
237
|
|
|
@@ -177,28 +256,35 @@ export default class AbstractControl extends foreElementMixin(HTMLElement) {
|
|
|
177
256
|
// console.log('mip valid', this.modelItem.required);
|
|
178
257
|
const alert = this.querySelector('fx-alert');
|
|
179
258
|
|
|
259
|
+
const mi = this.getModelItem();
|
|
260
|
+
console.log('late modelItem', mi);
|
|
180
261
|
if (this.isValid() !== this.modelItem.constraint) {
|
|
181
262
|
if (this.modelItem.constraint) {
|
|
182
|
-
if (alert) alert.style.display = 'none';
|
|
263
|
+
// if (alert) alert.style.display = 'none';
|
|
183
264
|
this._dispatchEvent('valid');
|
|
265
|
+
this.setAttribute('valid','');
|
|
184
266
|
this.removeAttribute('invalid');
|
|
185
267
|
} else {
|
|
186
268
|
this.setAttribute('invalid', '');
|
|
269
|
+
this.removeAttribute('valid');
|
|
187
270
|
// ### constraint is invalid - handle alerts
|
|
271
|
+
/*
|
|
188
272
|
if (alert) {
|
|
189
273
|
alert.style.display = 'block';
|
|
190
274
|
}
|
|
275
|
+
*/
|
|
191
276
|
if (this.modelItem.alerts.length !== 0) {
|
|
192
|
-
const { alerts } = this.modelItem;
|
|
193
|
-
// console.log('alerts from bind: ', alerts);
|
|
194
277
|
|
|
195
278
|
const controlAlert = this.querySelector('fx-alert');
|
|
196
279
|
if (!controlAlert) {
|
|
280
|
+
const { alerts } = this.modelItem;
|
|
281
|
+
// console.log('alerts from bind: ', alerts);
|
|
197
282
|
alerts.forEach(modelAlert => {
|
|
198
283
|
const newAlert = document.createElement('fx-alert');
|
|
284
|
+
// const newAlert = document.createElement('span');
|
|
199
285
|
newAlert.innerHTML = modelAlert;
|
|
200
286
|
this.appendChild(newAlert);
|
|
201
|
-
newAlert.style.display = 'block';
|
|
287
|
+
// newAlert.style.display = 'block';
|
|
202
288
|
});
|
|
203
289
|
}
|
|
204
290
|
}
|