ember-headless-form 1.0.0-beta.2 → 1.0.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/-private/components/control/input.js.map +1 -1
- package/dist/-private/components/field.d.ts +1 -1
- package/dist/-private/components/field.js +0 -1
- package/dist/-private/components/field.js.map +1 -1
- package/dist/-private/modifiers/capture-events.d.ts +2 -2
- package/dist/-private/modifiers/capture-events.js +8 -6
- package/dist/-private/modifiers/capture-events.js.map +1 -1
- package/dist/-private/utils.js.map +1 -1
- package/dist/components/headless-form.d.ts +27 -8
- package/dist/components/headless-form.js +81 -29
- package/dist/components/headless-form.js.map +1 -1
- package/package.json +16 -16
@@ -5,7 +5,7 @@ import '@babel/runtime/helpers/esm/initializerWarningHelper';
|
|
5
5
|
import { setComponentTemplate } from '@ember/component';
|
6
6
|
import { precompileTemplate } from '@ember/template-compilation';
|
7
7
|
import Component from '@glimmer/component';
|
8
|
-
import { tracked } from '@glimmer/tracking';
|
8
|
+
import { tracked, cached } from '@glimmer/tracking';
|
9
9
|
import { assert, warn } from '@ember/debug';
|
10
10
|
import { hash } from '@ember/helper';
|
11
11
|
import { on } from '@ember/modifier';
|
@@ -22,14 +22,16 @@ var _class, _descriptor, _class3, _descriptor2, _descriptor3, _descriptor4;
|
|
22
22
|
*/
|
23
23
|
let FieldData = (_class = class FieldData {
|
24
24
|
constructor(fieldRegistration) {
|
25
|
+
/**
|
26
|
+
* tracked state that enabled a dynamic validation of a field *before* the whole form is submitted, e.g. by `@validateOn="blur" and the blur event being triggered for that particular field.
|
27
|
+
*/
|
25
28
|
_initializerDefineProperty(this, "validationEnabled", _descriptor, this);
|
29
|
+
/**
|
30
|
+
* The *field* level validation callback passed to the field as in `<form.field @name="foo" @validate={{this.validateCallback}}>`
|
31
|
+
*/
|
26
32
|
_defineProperty(this, "validate", void 0);
|
27
33
|
this.validate = fieldRegistration.validate;
|
28
34
|
}
|
29
|
-
|
30
|
-
/**
|
31
|
-
* tracked state that enabled a dynamic validation of a field *before* the whole form is submitted, e.g. by `@validateOn="blur" and the blur event being triggered for that particular field.
|
32
|
-
*/
|
33
35
|
}, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "validationEnabled", [tracked], {
|
34
36
|
configurable: true,
|
35
37
|
enumerable: true,
|
@@ -74,22 +76,18 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
74
76
|
...attributes
|
75
77
|
{{this.registerForm}}
|
76
78
|
{{on "submit" this.onSubmit}}
|
77
|
-
{{
|
78
|
-
|
79
|
-
|
80
|
-
)}}
|
81
|
-
{{(if
|
79
|
+
{{on "reset" this.onReset}}
|
80
|
+
{{this.onValidation this.fieldValidationEvent this.handleFieldValidation}}
|
81
|
+
{{this.onValidation
|
82
82
|
this.fieldRevalidationEvent
|
83
|
-
|
84
|
-
|
85
|
-
)
|
86
|
-
)}}
|
83
|
+
this.handleFieldRevalidation
|
84
|
+
}}
|
87
85
|
>
|
88
86
|
{{yield
|
89
87
|
(hash
|
90
88
|
Field=(component
|
91
89
|
this.FieldComponent
|
92
|
-
data=this.
|
90
|
+
data=this.effectiveData
|
93
91
|
set=this.set
|
94
92
|
errors=this.visibleErrors
|
95
93
|
registerField=this.registerField
|
@@ -102,6 +100,8 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
102
100
|
submissionState=this.submissionState
|
103
101
|
isInvalid=this.hasValidationErrors
|
104
102
|
rawErrors=this.visibleErrors
|
103
|
+
submit=this.onSubmit
|
104
|
+
reset=this.onReset
|
105
105
|
)
|
106
106
|
}}
|
107
107
|
</form>
|
@@ -115,16 +115,61 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
115
115
|
constructor(...args) {
|
116
116
|
super(...args);
|
117
117
|
_defineProperty(this, "FieldComponent", HeadlessFormFieldComponent);
|
118
|
-
_defineProperty(this, "on", on);
|
119
118
|
_defineProperty(this, "formElement", void 0);
|
120
119
|
_defineProperty(this, "registerForm", modifier((el, _p) => {
|
121
120
|
this.formElement = el;
|
122
121
|
}));
|
123
|
-
|
122
|
+
/**
|
123
|
+
* A copy of the passed `@data` stored internally, which is only passed back to the component consumer after a (successful) form submission.
|
124
|
+
*/
|
125
|
+
_defineProperty(this, "internalData", new TrackedObject({}));
|
124
126
|
_defineProperty(this, "fields", new Map());
|
125
127
|
_initializerDefineProperty(this, "validationState", _descriptor2, this);
|
126
128
|
_initializerDefineProperty(this, "submissionState", _descriptor3, this);
|
129
|
+
/**
|
130
|
+
* When this is set to true by submitting the form, eventual validation errors are show for *all* field, regardless of their individual dynamic validation status in `FieldData#validationEnabled`
|
131
|
+
*/
|
127
132
|
_initializerDefineProperty(this, "showAllValidations", _descriptor4, this);
|
133
|
+
_defineProperty(this, "onValidation", modifier((el, [eventName, handler]) => {
|
134
|
+
if (eventName) {
|
135
|
+
el.addEventListener(eventName, handler);
|
136
|
+
return () => el.removeEventListener(eventName, handler);
|
137
|
+
}
|
138
|
+
}));
|
139
|
+
}
|
140
|
+
get effectiveData() {
|
141
|
+
const obj = this.args.data ?? {};
|
142
|
+
if (this.args.dataMode === 'mutable') {
|
143
|
+
return obj;
|
144
|
+
}
|
145
|
+
const {
|
146
|
+
internalData
|
147
|
+
} = this;
|
148
|
+
return new Proxy(obj, {
|
149
|
+
get(target, prop) {
|
150
|
+
return prop in internalData ? internalData[prop] : Reflect.get(target, prop);
|
151
|
+
},
|
152
|
+
set(target, property, value) {
|
153
|
+
return Reflect.set(internalData, property, value);
|
154
|
+
},
|
155
|
+
has(target, prop) {
|
156
|
+
return prop in internalData ? true : Reflect.has(target, prop);
|
157
|
+
},
|
158
|
+
getOwnPropertyDescriptor(target, prop) {
|
159
|
+
return Reflect.getOwnPropertyDescriptor(prop in internalData ? internalData : target, prop);
|
160
|
+
},
|
161
|
+
ownKeys(target) {
|
162
|
+
return [...Reflect.ownKeys(target), ...Reflect.ownKeys(internalData)]
|
163
|
+
// return only unique values
|
164
|
+
.filter((value, index, array) => array.indexOf(value) === index);
|
165
|
+
},
|
166
|
+
deleteProperty(target, prop) {
|
167
|
+
if (prop in internalData) {
|
168
|
+
delete internalData[prop];
|
169
|
+
}
|
170
|
+
return true;
|
171
|
+
}
|
172
|
+
});
|
128
173
|
}
|
129
174
|
get validateOn() {
|
130
175
|
return this.args.validateOn ?? 'submit';
|
@@ -177,10 +222,10 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
177
222
|
*/
|
178
223
|
async validate() {
|
179
224
|
const nativeValidation = this.args.ignoreNativeValidation !== true ? this.validateNative() : {};
|
180
|
-
const customFormValidation = await this.args.validate?.(this.
|
225
|
+
const customFormValidation = await this.args.validate?.(this.effectiveData, Array.from(this.fields.keys()));
|
181
226
|
const customFieldValidations = [];
|
182
227
|
for (const [name, field] of this.fields) {
|
183
|
-
const fieldValidationResult = await field.validate?.(this.
|
228
|
+
const fieldValidationResult = await field.validate?.(this.effectiveData[name], name, this.effectiveData);
|
184
229
|
if (fieldValidationResult) {
|
185
230
|
customFieldValidations.push({
|
186
231
|
[name]: fieldValidationResult
|
@@ -191,7 +236,7 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
191
236
|
}
|
192
237
|
async _validate() {
|
193
238
|
const promise = this.validate();
|
194
|
-
this.validationState = new TrackedAsyncData(promise
|
239
|
+
this.validationState = new TrackedAsyncData(promise);
|
195
240
|
return promise;
|
196
241
|
}
|
197
242
|
validateNative() {
|
@@ -211,7 +256,7 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
211
256
|
if (this.fields.has(name)) {
|
212
257
|
errors[name] = [{
|
213
258
|
type: 'native',
|
214
|
-
value: this.
|
259
|
+
value: this.effectiveData[name],
|
215
260
|
message: el.validationMessage
|
216
261
|
}];
|
217
262
|
} else {
|
@@ -248,17 +293,25 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
248
293
|
return this.showAllValidations || (this.fields.get(field)?.validationEnabled ?? false);
|
249
294
|
}
|
250
295
|
async onSubmit(e) {
|
251
|
-
e
|
296
|
+
e?.preventDefault();
|
252
297
|
await this._validate();
|
253
298
|
this.showAllValidations = true;
|
254
299
|
if (!this.hasValidationErrors) {
|
255
300
|
if (this.args.onSubmit) {
|
256
|
-
this.submissionState = new TrackedAsyncData(this.args.onSubmit(this.
|
301
|
+
this.submissionState = new TrackedAsyncData(this.args.onSubmit(this.effectiveData));
|
257
302
|
}
|
258
303
|
} else {
|
259
304
|
assert('Validation errors expected to be present. If you see this, please report it as a bug to ember-headless-form!', this.validationState?.isResolved);
|
260
|
-
this.args.onInvalid?.(this.
|
305
|
+
this.args.onInvalid?.(this.effectiveData, this.validationState.value);
|
306
|
+
}
|
307
|
+
}
|
308
|
+
async onReset(e) {
|
309
|
+
e?.preventDefault();
|
310
|
+
for (const key of Object.keys(this.internalData)) {
|
311
|
+
delete this.internalData[key];
|
261
312
|
}
|
313
|
+
this.validationState = undefined;
|
314
|
+
this.submissionState = undefined;
|
262
315
|
}
|
263
316
|
registerField(name, field) {
|
264
317
|
assert(`You passed @name="${String(name)}" to the form field, but this is already in use. Names of form fields must be unique!`, !this.fields.has(name));
|
@@ -268,8 +321,8 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
268
321
|
this.fields.delete(name);
|
269
322
|
}
|
270
323
|
set(key, value) {
|
271
|
-
// when @mutableData is set, our
|
272
|
-
set(this.
|
324
|
+
// when @mutableData is set, our effectiveData is something we don't control, i.e. might require old-school set() to be on the safe side
|
325
|
+
set(this.effectiveData, key, value);
|
273
326
|
}
|
274
327
|
|
275
328
|
/**
|
@@ -324,7 +377,7 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
324
377
|
});
|
325
378
|
}
|
326
379
|
}
|
327
|
-
}, (_descriptor2 = _applyDecoratedDescriptor(_class3.prototype, "validationState", [tracked], {
|
380
|
+
}, (_applyDecoratedDescriptor(_class3.prototype, "effectiveData", [cached], Object.getOwnPropertyDescriptor(_class3.prototype, "effectiveData"), _class3.prototype), _descriptor2 = _applyDecoratedDescriptor(_class3.prototype, "validationState", [tracked], {
|
328
381
|
configurable: true,
|
329
382
|
enumerable: true,
|
330
383
|
writable: true,
|
@@ -341,8 +394,7 @@ let HeadlessFormComponent = setComponentTemplate(precompileTemplate(`
|
|
341
394
|
initializer: function () {
|
342
395
|
return false;
|
343
396
|
}
|
344
|
-
}), _applyDecoratedDescriptor(_class3.prototype, "onSubmit", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "onSubmit"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "registerField", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "registerField"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "unregisterField", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "unregisterField"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "set", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "set"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "handleFieldValidation", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "handleFieldValidation"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "handleFieldRevalidation", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "handleFieldRevalidation"), _class3.prototype)), _class3));
|
345
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- workaround for unknown modifier helper: https://github.com/typed-ember/glint/issues/410
|
397
|
+
}), _applyDecoratedDescriptor(_class3.prototype, "onSubmit", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "onSubmit"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "onReset", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "onReset"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "registerField", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "registerField"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "unregisterField", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "unregisterField"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "set", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "set"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "handleFieldValidation", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "handleFieldValidation"), _class3.prototype), _applyDecoratedDescriptor(_class3.prototype, "handleFieldRevalidation", [action], Object.getOwnPropertyDescriptor(_class3.prototype, "handleFieldRevalidation"), _class3.prototype)), _class3));
|
346
398
|
|
347
399
|
export { HeadlessFormComponent as default };
|
348
400
|
//# sourceMappingURL=headless-form.js.map
|