neo.mjs 5.1.17 → 5.2.1
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/apps/ServiceWorker.mjs +2 -2
- package/apps/form/view/ViewportController.mjs +41 -12
- package/apps/form/view/pages/Page3.mjs +4 -3
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +1 -1
- package/resources/scss/src/form/field/Text.scss +1 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/form/Container.mjs +71 -39
- package/src/form/field/Text.mjs +16 -8
- package/src/layout/Card.mjs +3 -0
package/apps/ServiceWorker.mjs
CHANGED
@@ -16,30 +16,59 @@ class ViewportController extends Component {
|
|
16
16
|
/**
|
17
17
|
* @param {Object} data
|
18
18
|
*/
|
19
|
-
onValidateAllPagesButtonClick(data) {
|
20
|
-
let me
|
21
|
-
form
|
22
|
-
isValid
|
19
|
+
async onValidateAllPagesButtonClick(data) {
|
20
|
+
let me = this,
|
21
|
+
form = me.getReference('main-form'),
|
22
|
+
isValid = await form.validate(),
|
23
|
+
formValues = await form.getValues();
|
23
24
|
|
24
|
-
console.log('
|
25
|
+
console.log('All pages', {isValid, formValues});
|
26
|
+
|
27
|
+
await me.updateRecordValidityState()
|
25
28
|
}
|
26
29
|
|
27
30
|
/**
|
28
31
|
* @param {Object} data
|
29
32
|
*/
|
30
|
-
onValidatePageButtonClick(data) {
|
33
|
+
async onValidatePageButtonClick(data) {
|
34
|
+
let me = this,
|
35
|
+
activeIndex = me.getModel().data.activeIndex,
|
36
|
+
activeCard = me.getReference('pages-container').items[activeIndex],
|
37
|
+
formValues = await activeCard.getValues();
|
38
|
+
|
39
|
+
await activeCard.validate();
|
40
|
+
await me.updateRecordValidityState(activeIndex)
|
41
|
+
|
42
|
+
console.log(`Current page: ${activeIndex + 1}`, formValues);
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Not passing a pageIndex validates all pages
|
47
|
+
* @param {Number|null} [pageIndex]
|
48
|
+
* @returns {Promise<void>}
|
49
|
+
*/
|
50
|
+
async updateRecordValidityState(pageIndex=null) {
|
31
51
|
let me = this,
|
32
52
|
model = me.getModel(),
|
33
|
-
activeIndex = model.data.activeIndex,
|
34
53
|
pagesContainer = me.getReference('pages-container'),
|
54
|
+
sideNav = me.getReference('side-nav'),
|
35
55
|
store = model.getStore('sideNav'),
|
36
|
-
|
37
|
-
|
38
|
-
isValid
|
56
|
+
i = 0,
|
57
|
+
len = pagesContainer.items.length,
|
58
|
+
isValid, listIndex, page;
|
59
|
+
|
60
|
+
if (Neo.isNumber(pageIndex)) {
|
61
|
+
i = pageIndex;
|
62
|
+
len = pageIndex + 1;
|
63
|
+
}
|
39
64
|
|
40
|
-
|
65
|
+
for (; i < len; i++) {
|
66
|
+
page = pagesContainer.items[i];
|
67
|
+
listIndex = sideNav.getActiveIndex(i);
|
68
|
+
isValid = await page.isValid();
|
41
69
|
|
42
|
-
|
70
|
+
store.getAt(listIndex).isValid = isValid;
|
71
|
+
}
|
43
72
|
}
|
44
73
|
}
|
45
74
|
|
@@ -18,12 +18,13 @@ class Page3 extends FormPageContainer {
|
|
18
18
|
items: [{
|
19
19
|
module : TextField,
|
20
20
|
labelText: 'Page 3 Field 1',
|
21
|
-
name : '
|
22
|
-
required : true
|
21
|
+
name : 'page3.field1',
|
22
|
+
required : true,
|
23
|
+
value : 'foo'
|
23
24
|
}, {
|
24
25
|
module : TextField,
|
25
26
|
labelText: 'Page 3 Field 2',
|
26
|
-
name : '
|
27
|
+
name : 'page3.field2'
|
27
28
|
}]
|
28
29
|
}
|
29
30
|
}
|
package/package.json
CHANGED
package/src/DefaultConfig.mjs
CHANGED
@@ -237,12 +237,12 @@ const DefaultConfig = {
|
|
237
237
|
useVdomWorker: true,
|
238
238
|
/**
|
239
239
|
* buildScripts/injectPackageVersion.mjs will update this value
|
240
|
-
* @default '5.1
|
240
|
+
* @default '5.2.1'
|
241
241
|
* @memberOf! module:Neo
|
242
242
|
* @name config.version
|
243
243
|
* @type String
|
244
244
|
*/
|
245
|
-
version: '5.1
|
245
|
+
version: '5.2.1'
|
246
246
|
};
|
247
247
|
|
248
248
|
Object.assign(DefaultConfig, {
|
package/src/form/Container.mjs
CHANGED
@@ -31,30 +31,30 @@ class Container extends BaseContainer {
|
|
31
31
|
}
|
32
32
|
|
33
33
|
/**
|
34
|
+
* @param {Neo.container.Base} parent
|
35
|
+
* @param {Object[]} modules
|
34
36
|
* @returns {Object[]}
|
35
37
|
*/
|
36
|
-
findNotLoadedModules(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
if (Neo.typeOf(item.module) === 'Function') {
|
41
|
-
modules.push(item)
|
38
|
+
findNotLoadedModules(parent=this, modules=[]) {
|
39
|
+
parent.items.forEach(item => {
|
40
|
+
if (Neo.typeOf(item.module) === 'Function' && !item.isLoading) {
|
41
|
+
modules.push({item, parent});
|
42
42
|
} else {
|
43
|
-
item.items && this.findNotLoadedModules(item);
|
43
|
+
item.items && this.findNotLoadedModules(item, modules);
|
44
44
|
}
|
45
45
|
});
|
46
46
|
|
47
|
-
console.log(modules);
|
48
|
-
|
49
47
|
return modules;
|
50
48
|
}
|
51
49
|
|
52
50
|
/**
|
53
|
-
* Either pass a field
|
51
|
+
* Either pass a field name or id
|
54
52
|
* @param {String} name
|
55
|
-
* @returns {Neo.form.field.Base|null} fields
|
53
|
+
* @returns {Promise<Neo.form.field.Base|null>} fields
|
56
54
|
*/
|
57
|
-
getField(name) {
|
55
|
+
async getField(name) {
|
56
|
+
await this.loadModules();
|
57
|
+
|
58
58
|
let fields = ComponentManager.getChildComponents(this),
|
59
59
|
field;
|
60
60
|
|
@@ -70,12 +70,12 @@ class Container extends BaseContainer {
|
|
70
70
|
}
|
71
71
|
|
72
72
|
/**
|
73
|
-
* @returns {Neo.form.field.Base[]} fields
|
73
|
+
* @returns {Promise<Neo.form.field.Base[]>} fields
|
74
74
|
*/
|
75
|
-
getFields() {
|
75
|
+
async getFields() {
|
76
76
|
let fields = [];
|
77
77
|
|
78
|
-
this.
|
78
|
+
await this.loadModules();
|
79
79
|
|
80
80
|
ComponentManager.getChildComponents(this).forEach(item => {
|
81
81
|
item instanceof BaseField && fields.push(item);
|
@@ -85,12 +85,13 @@ class Container extends BaseContainer {
|
|
85
85
|
}
|
86
86
|
|
87
87
|
/**
|
88
|
-
* @returns {Object}
|
88
|
+
* @returns {Promise<Object>}
|
89
89
|
*/
|
90
|
-
getSubmitValues() {
|
91
|
-
let
|
90
|
+
async getSubmitValues() {
|
91
|
+
let fields = await this.getFields(),
|
92
|
+
values = {};
|
92
93
|
|
93
|
-
|
94
|
+
fields.forEach(item => {
|
94
95
|
values[item.name || item.id] = item.getSubmitValue();
|
95
96
|
});
|
96
97
|
|
@@ -98,13 +99,23 @@ class Container extends BaseContainer {
|
|
98
99
|
}
|
99
100
|
|
100
101
|
/**
|
101
|
-
* @returns {Object}
|
102
|
+
* @returns {Promise<Object>}
|
102
103
|
*/
|
103
|
-
getValues() {
|
104
|
-
let
|
105
|
-
|
106
|
-
|
107
|
-
|
104
|
+
async getValues() {
|
105
|
+
let fields = await this.getFields(),
|
106
|
+
values = {},
|
107
|
+
key, ns, nsArray;
|
108
|
+
|
109
|
+
fields.forEach(item => {
|
110
|
+
if (item.name) {
|
111
|
+
nsArray = item.name.split('.');
|
112
|
+
key = nsArray.pop();
|
113
|
+
ns = Neo.ns(nsArray, true, values);
|
114
|
+
|
115
|
+
ns[key] = item.value;
|
116
|
+
} else {
|
117
|
+
values[item.id] = item.value;
|
118
|
+
}
|
108
119
|
});
|
109
120
|
|
110
121
|
return values;
|
@@ -112,10 +123,10 @@ class Container extends BaseContainer {
|
|
112
123
|
|
113
124
|
/**
|
114
125
|
* Returns true in case no form field isValid() call returns false
|
115
|
-
* @returns {Boolean}
|
126
|
+
* @returns {Promise<Boolean>}
|
116
127
|
*/
|
117
|
-
isValid() {
|
118
|
-
let fields = this.getFields(),
|
128
|
+
async isValid() {
|
129
|
+
let fields = await this.getFields(),
|
119
130
|
i = 0,
|
120
131
|
len = fields.length;
|
121
132
|
|
@@ -128,16 +139,35 @@ class Container extends BaseContainer {
|
|
128
139
|
return true;
|
129
140
|
}
|
130
141
|
|
142
|
+
/**
|
143
|
+
* Loads all not loaded items inside card layouts
|
144
|
+
* @returns {Promise<Neo.component.Base[]>}
|
145
|
+
*/
|
146
|
+
async loadModules() {
|
147
|
+
let me = this,
|
148
|
+
modules = me.findNotLoadedModules(),
|
149
|
+
promises = [];
|
150
|
+
|
151
|
+
modules.forEach(module => {
|
152
|
+
promises.push(module.parent.layout.loadModule(module.item));
|
153
|
+
});
|
154
|
+
|
155
|
+
modules = await Promise.all(promises);
|
156
|
+
|
157
|
+
return modules;
|
158
|
+
}
|
159
|
+
|
131
160
|
/**
|
132
161
|
* Resets field values by field name or field id.
|
133
162
|
* Fields not included with a value will get reset to null.
|
134
163
|
* @param {Object} [values]
|
135
164
|
*/
|
136
|
-
reset(values={}) {
|
137
|
-
let keys
|
165
|
+
async reset(values={}) {
|
166
|
+
let keys = values ? Object.keys(values) : [],
|
167
|
+
fields = await this.getFields(),
|
138
168
|
index;
|
139
169
|
|
140
|
-
|
170
|
+
fields.forEach(item => {
|
141
171
|
index = keys.indexOf(item.name);
|
142
172
|
|
143
173
|
if (index < 0) {
|
@@ -145,18 +175,19 @@ class Container extends BaseContainer {
|
|
145
175
|
}
|
146
176
|
|
147
177
|
item.reset(index > -1 ? values[keys[index]] : null);
|
148
|
-
})
|
178
|
+
})
|
149
179
|
}
|
150
180
|
|
151
181
|
/**
|
152
182
|
* Set field values by field name or field id
|
153
183
|
* @param {Object} values={}
|
154
184
|
*/
|
155
|
-
setValues(values={}) {
|
156
|
-
let keys
|
185
|
+
async setValues(values={}) {
|
186
|
+
let keys = Object.keys(values),
|
187
|
+
fields = await this.getFields(),
|
157
188
|
index;
|
158
189
|
|
159
|
-
|
190
|
+
fields.forEach(item => {
|
160
191
|
index = keys.indexOf(item.name);
|
161
192
|
|
162
193
|
if (index < 0) {
|
@@ -166,19 +197,20 @@ class Container extends BaseContainer {
|
|
166
197
|
if (index > -1) {
|
167
198
|
item.value = values[keys[index]];
|
168
199
|
}
|
169
|
-
})
|
200
|
+
})
|
170
201
|
}
|
171
202
|
|
172
203
|
/**
|
173
204
|
* Updates the invalid state for all fields which have validate() implemented.
|
174
205
|
* This can be useful for create-entity forms which show up "clean" until pressing a submit button.
|
175
|
-
* @returns {Boolean}
|
206
|
+
* @returns {Promise<Boolean>}
|
176
207
|
*/
|
177
|
-
validate() {
|
208
|
+
async validate() {
|
178
209
|
let isValid = true,
|
210
|
+
fields = await this.getFields(),
|
179
211
|
validField;
|
180
212
|
|
181
|
-
|
213
|
+
fields.forEach(item => {
|
182
214
|
validField = item.validate?.(false);
|
183
215
|
|
184
216
|
if (!validField) {
|
package/src/form/field/Text.mjs
CHANGED
@@ -175,6 +175,12 @@ class Text extends Base {
|
|
175
175
|
]}
|
176
176
|
}
|
177
177
|
|
178
|
+
/**
|
179
|
+
* Set this value to false, in case a field should display errors up front.
|
180
|
+
* Otherwise, errors will stay hidden on mounting, unless you trigger validate(false).
|
181
|
+
* @member {Boolean} clean=true
|
182
|
+
*/
|
183
|
+
clean = true
|
178
184
|
/**
|
179
185
|
* data passes maxLength, minLength & valueLength properties
|
180
186
|
* @member {Function} errorTextMaxLength=data=>`Max length violation: ${valueLength} / ${maxLength}`
|
@@ -189,11 +195,6 @@ class Text extends Base {
|
|
189
195
|
* @member {String} errorTextRequired='Required'
|
190
196
|
*/
|
191
197
|
errorTextRequired = 'Required'
|
192
|
-
/**
|
193
|
-
* Set this value to false, in case a field should display errors up front
|
194
|
-
* @member {Boolean} validBeforeMount=true
|
195
|
-
*/
|
196
|
-
validBeforeMount = true
|
197
198
|
|
198
199
|
/**
|
199
200
|
* @param {Object} config
|
@@ -1088,11 +1089,13 @@ class Text extends Base {
|
|
1088
1089
|
onFocusLeave(data) {
|
1089
1090
|
let me = this,
|
1090
1091
|
centerBorderEl = me.getCenterBorderEl(), // labelPosition: 'inline'
|
1091
|
-
cls
|
1092
|
+
cls;
|
1092
1093
|
|
1093
1094
|
if (!me.readOnly) {
|
1094
1095
|
me.validate(); // silent
|
1095
1096
|
|
1097
|
+
cls = me.cls; // has to get set after validate()
|
1098
|
+
|
1096
1099
|
NeoArray.remove(cls, 'neo-focus');
|
1097
1100
|
me.cls = cls;
|
1098
1101
|
|
@@ -1202,7 +1205,7 @@ class Text extends Base {
|
|
1202
1205
|
|
1203
1206
|
super.reset(value);
|
1204
1207
|
|
1205
|
-
if (value === null && me.
|
1208
|
+
if (value === null && me.clean) {
|
1206
1209
|
me.updateError(null);
|
1207
1210
|
}
|
1208
1211
|
}
|
@@ -1234,7 +1237,7 @@ class Text extends Base {
|
|
1234
1237
|
cls = me.cls,
|
1235
1238
|
errorNode, isValid;
|
1236
1239
|
|
1237
|
-
if (!(me.
|
1240
|
+
if (!(me.clean && !me.mounted)) {
|
1238
1241
|
me._error = value;
|
1239
1242
|
|
1240
1243
|
isValid = !value || value === '';
|
@@ -1312,6 +1315,11 @@ class Text extends Base {
|
|
1312
1315
|
errorParam = {maxLength, minLength, valueLength},
|
1313
1316
|
errorText;
|
1314
1317
|
|
1318
|
+
if (!silent) {
|
1319
|
+
// in case we manually call validate(false) on a form or field before it is mounted, we do want to see errors.
|
1320
|
+
me.clean = false;
|
1321
|
+
}
|
1322
|
+
|
1315
1323
|
if (Neo.isFunction(me.validator)) {
|
1316
1324
|
errorText = me.validator(me);
|
1317
1325
|
|
package/src/layout/Card.mjs
CHANGED
@@ -184,6 +184,8 @@ class Card extends Base {
|
|
184
184
|
index = items.indexOf(item);
|
185
185
|
}
|
186
186
|
|
187
|
+
item.isLoading = true; // prevent the item from getting queued multiple times inside form.Container
|
188
|
+
|
187
189
|
module = await module();
|
188
190
|
module = module.default;
|
189
191
|
proto = module.prototype;
|
@@ -193,6 +195,7 @@ class Card extends Base {
|
|
193
195
|
item.wrapperCls = [...wrapperCls, sCfg.itemCls];
|
194
196
|
item.module = module;
|
195
197
|
|
198
|
+
delete item.isLoading;
|
196
199
|
delete item.vdom;
|
197
200
|
|
198
201
|
items[index] = item = Neo.create(item);
|