@conform-to/react 0.5.0-pre.0 → 0.5.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/helpers.d.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import type { FieldConfig } from '@conform-to/dom';
2
2
  import type { HTMLInputTypeAttribute } from 'react';
3
3
  interface FieldProps {
4
+ id?: string;
4
5
  name: string;
5
6
  form?: string;
6
7
  required?: boolean;
7
8
  autoFocus?: boolean;
9
+ 'aria-invalid': boolean;
10
+ 'aria-describedby'?: string;
8
11
  }
9
12
  interface InputProps<Schema> extends FieldProps {
10
13
  type?: HTMLInputTypeAttribute;
package/helpers.js CHANGED
@@ -3,8 +3,10 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  function input(config) {
6
+ var _config$initialError;
6
7
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7
8
  var attributes = {
9
+ id: config.id,
8
10
  type: options.type,
9
11
  name: config.name,
10
12
  form: config.form,
@@ -15,7 +17,9 @@ function input(config) {
15
17
  max: config.max,
16
18
  step: config.step,
17
19
  pattern: config.pattern,
18
- multiple: config.multiple
20
+ multiple: config.multiple,
21
+ 'aria-invalid': Boolean((_config$initialError = config.initialError) === null || _config$initialError === void 0 ? void 0 : _config$initialError.length),
22
+ 'aria-describedby': config.errorId
19
23
  };
20
24
  if (config.initialError && config.initialError.length > 0) {
21
25
  attributes.autoFocus = true;
@@ -30,13 +34,16 @@ function input(config) {
30
34
  return attributes;
31
35
  }
32
36
  function select(config) {
33
- var _config$defaultValue;
37
+ var _config$defaultValue, _config$initialError2;
34
38
  var attributes = {
39
+ id: config.id,
35
40
  name: config.name,
36
41
  form: config.form,
37
42
  defaultValue: config.multiple ? Array.isArray(config.defaultValue) ? config.defaultValue : [] : "".concat((_config$defaultValue = config.defaultValue) !== null && _config$defaultValue !== void 0 ? _config$defaultValue : ''),
38
43
  required: config.required,
39
- multiple: config.multiple
44
+ multiple: config.multiple,
45
+ 'aria-invalid': Boolean((_config$initialError2 = config.initialError) === null || _config$initialError2 === void 0 ? void 0 : _config$initialError2.length),
46
+ 'aria-describedby': config.errorId
40
47
  };
41
48
  if (config.initialError && config.initialError.length > 0) {
42
49
  attributes.autoFocus = true;
@@ -44,15 +51,18 @@ function select(config) {
44
51
  return attributes;
45
52
  }
46
53
  function textarea(config) {
47
- var _config$defaultValue2;
54
+ var _config$defaultValue2, _config$initialError3;
48
55
  var attributes = {
56
+ id: config.id,
49
57
  name: config.name,
50
58
  form: config.form,
51
59
  defaultValue: "".concat((_config$defaultValue2 = config.defaultValue) !== null && _config$defaultValue2 !== void 0 ? _config$defaultValue2 : ''),
52
60
  required: config.required,
53
61
  minLength: config.minLength,
54
62
  maxLength: config.maxLength,
55
- autoFocus: Boolean(config.initialError)
63
+ autoFocus: Boolean(config.initialError),
64
+ 'aria-invalid': Boolean((_config$initialError3 = config.initialError) === null || _config$initialError3 === void 0 ? void 0 : _config$initialError3.length),
65
+ 'aria-describedby': config.errorId
56
66
  };
57
67
  if (config.initialError && config.initialError.length > 0) {
58
68
  attributes.autoFocus = true;
package/hooks.d.ts CHANGED
@@ -1,6 +1,11 @@
1
- import { type FieldConfig, type FieldElement, type FieldValue, type FieldsetConstraint, type ListCommand, type Primitive, type Submission } from '@conform-to/dom';
1
+ import { type FieldConfig, type FieldElement, type FieldValue, type FieldsetConstraint, type Primitive, type Submission } from '@conform-to/dom';
2
2
  import { type InputHTMLAttributes, type FormEvent, type RefObject } from 'react';
3
3
  export interface FormConfig<Schema extends Record<string, any>> {
4
+ /**
5
+ * If the form id is provided, Id for label,
6
+ * input and error elements will be derived.
7
+ */
8
+ id?: string;
4
9
  /**
5
10
  * Validation mode. Default to `client-only`.
6
11
  */
@@ -20,6 +25,10 @@ export interface FormConfig<Schema extends Record<string, any>> {
20
25
  * An object describing the state from the last submission
21
26
  */
22
27
  state?: Submission<Schema>;
28
+ /**
29
+ * An object describing the constraint of each field
30
+ */
31
+ constraint?: FieldsetConstraint<Schema>;
23
32
  /**
24
33
  * Enable native validation before hydation.
25
34
  *
@@ -53,10 +62,12 @@ export interface FormConfig<Schema extends Record<string, any>> {
53
62
  */
54
63
  interface FormProps {
55
64
  ref: RefObject<HTMLFormElement>;
65
+ id?: string;
56
66
  onSubmit: (event: FormEvent<HTMLFormElement>) => void;
57
67
  noValidate: boolean;
58
68
  }
59
69
  interface Form<Schema extends Record<string, any>> {
70
+ id?: string;
60
71
  ref: RefObject<HTMLFormElement>;
61
72
  error: string;
62
73
  props: FormProps;
@@ -66,9 +77,9 @@ interface Form<Schema extends Record<string, any>> {
66
77
  * Returns properties required to hook into form events.
67
78
  * Applied custom validation and define when error should be reported.
68
79
  *
69
- * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#useform
80
+ * @see https://conform.guide/api/react#useform
70
81
  */
71
- export declare function useForm<Schema extends Record<string, any>>(config?: FormConfig<Schema>): Form<Schema>;
82
+ export declare function useForm<Schema extends Record<string, any>>(config?: FormConfig<Schema>): [Form<Schema>, Fieldset<Schema>];
72
83
  /**
73
84
  * All the information of the field, including state and config.
74
85
  */
@@ -107,39 +118,21 @@ export interface FieldsetConfig<Schema extends Record<string, any>> {
107
118
  /**
108
119
  * Returns all the information about the fieldset.
109
120
  *
110
- * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usefieldset
121
+ * @see https://conform.guide/api/react#usefieldset
111
122
  */
112
123
  export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldsetConfig<Schema>): Fieldset<Schema>;
113
124
  export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldConfig<Schema>): Fieldset<Schema>;
114
- interface CommandButtonProps {
115
- name?: string;
116
- value?: string;
117
- form?: string;
118
- formNoValidate: true;
119
- }
120
- declare type ListCommandPayload<Schema, Type extends ListCommand<FieldValue<Schema>>['type']> = Extract<ListCommand<FieldValue<Schema>>, {
121
- type: Type;
122
- }>['payload'];
123
125
  /**
124
126
  * Returns a list of key and config, with a group of helpers
125
127
  * configuring buttons for list manipulation
126
128
  *
127
- * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usefieldlist
129
+ * @see https://conform.guide/api/react#usefieldlist
128
130
  */
129
- export declare function useFieldList<Payload = any>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldConfig<Array<Payload>>): [
130
- Array<{
131
- key: string;
132
- error: string | undefined;
133
- config: FieldConfig<Payload>;
134
- }>,
135
- {
136
- prepend(payload?: ListCommandPayload<Payload, 'prepend'>): CommandButtonProps;
137
- append(payload?: ListCommandPayload<Payload, 'append'>): CommandButtonProps;
138
- replace(payload: ListCommandPayload<Payload, 'replace'>): CommandButtonProps;
139
- remove(payload: ListCommandPayload<Payload, 'remove'>): CommandButtonProps;
140
- reorder(payload: ListCommandPayload<Payload, 'reorder'>): CommandButtonProps;
141
- }
142
- ];
131
+ export declare function useFieldList<Payload = any>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldConfig<Array<Payload>>): Array<{
132
+ key: string;
133
+ error: string | undefined;
134
+ config: FieldConfig<Payload>;
135
+ }>;
143
136
  interface ShadowInputProps extends InputHTMLAttributes<HTMLInputElement> {
144
137
  ref: RefObject<HTMLInputElement>;
145
138
  }
@@ -161,7 +154,7 @@ interface InputControl<Element extends {
161
154
  * This is particular useful when integrating dropdown and datepicker whichs
162
155
  * introduces custom input mode.
163
156
  *
164
- * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usecontrolledinput
157
+ * @see https://conform.guide/api/react#usecontrolledinput
165
158
  */
166
159
  export declare function useControlledInput<Element extends {
167
160
  focus: () => void;
package/hooks.js CHANGED
@@ -11,7 +11,7 @@ var helpers = require('./helpers.js');
11
11
  * Returns properties required to hook into form events.
12
12
  * Applied custom validation and define when error should be reported.
13
13
  *
14
- * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#useform
14
+ * @see https://conform.guide/api/react#useform
15
15
  */
16
16
  function useForm() {
17
17
  var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -25,17 +25,26 @@ function useForm() {
25
25
  })) !== null && _config$state$error$f !== void 0 ? _config$state$error$f : [];
26
26
  return message !== null && message !== void 0 ? message : '';
27
27
  });
28
- var [fieldsetConfig, setFieldsetConfig] = react.useState(() => {
29
- var _config$state$error2, _config$state2, _config$state$value, _config$state3;
30
- var error = (_config$state$error2 = (_config$state2 = config.state) === null || _config$state2 === void 0 ? void 0 : _config$state2.error) !== null && _config$state$error2 !== void 0 ? _config$state$error2 : [];
28
+ var [uncontrolledState, setUncontrolledState] = react.useState(() => {
29
+ var submission = config.state;
30
+ if (!submission) {
31
+ return {
32
+ defaultValue: config.defaultValue
33
+ };
34
+ }
31
35
  return {
32
- defaultValue: (_config$state$value = (_config$state3 = config.state) === null || _config$state3 === void 0 ? void 0 : _config$state3.value) !== null && _config$state$value !== void 0 ? _config$state$value : config.defaultValue,
33
- initialError: error.filter(_ref2 => {
36
+ defaultValue: submission.value,
37
+ initialError: submission.error.filter(_ref2 => {
34
38
  var [name] = _ref2;
35
- return name !== '' && dom.getSubmissionType(name) === null;
39
+ return name !== '' && dom.shouldValidate(submission, name);
36
40
  })
37
41
  };
38
42
  });
43
+ var fieldsetConfig = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, uncontrolledState), {}, {
44
+ constraint: config.constraint,
45
+ form: config.id
46
+ });
47
+ var fieldset = useFieldset(ref, fieldsetConfig);
39
48
  var [noValidate, setNoValidate] = react.useState(config.noValidate || !config.fallbackNative);
40
49
  react.useEffect(() => {
41
50
  configRef.current = config;
@@ -59,11 +68,8 @@ function useForm() {
59
68
  if (!form || !dom.isFieldElement(field) || field.form !== form) {
60
69
  return;
61
70
  }
62
- if (formConfig.initialReport === 'onChange') {
63
- field.dataset.conformTouched = 'true';
64
- }
65
- if (field.dataset.conformTouched) {
66
- dom.requestValidate(form, field.name);
71
+ if (field.dataset.conformTouched || formConfig.initialReport === 'onChange') {
72
+ dom.requestCommand(form, dom.validate(field.name));
67
73
  }
68
74
  };
69
75
  var handleBlur = event => {
@@ -74,8 +80,7 @@ function useForm() {
74
80
  return;
75
81
  }
76
82
  if (formConfig.initialReport === 'onBlur' && !field.dataset.conformTouched) {
77
- field.dataset.conformTouched = 'true';
78
- dom.requestValidate(form, field.name);
83
+ dom.requestCommand(form, dom.validate(field.name));
79
84
  }
80
85
  };
81
86
  var handleInvalid = event => {
@@ -100,11 +105,12 @@ function useForm() {
100
105
  for (var field of form.elements) {
101
106
  if (dom.isFieldElement(field)) {
102
107
  delete field.dataset.conformTouched;
108
+ field.setAttribute('aria-invalid', 'false');
103
109
  field.setCustomValidity('');
104
110
  }
105
111
  }
106
112
  setError('');
107
- setFieldsetConfig({
113
+ setUncontrolledState({
108
114
  defaultValue: formConfig.defaultValue,
109
115
  initialError: []
110
116
  });
@@ -127,11 +133,13 @@ function useForm() {
127
133
  document.removeEventListener('reset', handleReset);
128
134
  };
129
135
  }, []);
130
- return {
136
+ var form = {
137
+ id: config.id,
131
138
  ref,
132
139
  error,
133
140
  props: {
134
141
  ref,
142
+ id: config.id,
135
143
  noValidate,
136
144
  onSubmit(event) {
137
145
  var form = event.currentTarget;
@@ -173,16 +181,6 @@ function useForm() {
173
181
  }
174
182
  }
175
183
  }
176
-
177
- // Touch all fields only if the submitter is not a command button
178
- if (submission.type === 'submit') {
179
- for (var field of form.elements) {
180
- if (dom.isFieldElement(field)) {
181
- // Mark the field as touched
182
- field.dataset.conformTouched = 'true';
183
- }
184
- }
185
- }
186
184
  if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && dom.hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
187
185
  event.preventDefault();
188
186
  } else {
@@ -202,6 +200,7 @@ function useForm() {
202
200
  },
203
201
  config: fieldsetConfig
204
202
  };
203
+ return [form, fieldset];
205
204
  }
206
205
 
207
206
  /**
@@ -262,6 +261,10 @@ function useFieldset(ref, config) {
262
261
  // Update the error only if the field belongs to the fieldset
263
262
  if (typeof key === 'string' && paths.length === 0) {
264
263
  if (field.dataset.conformTouched) {
264
+ // Update the aria attribute only if it is set
265
+ if (field.getAttribute('aria-invalid')) {
266
+ field.setAttribute('aria-invalid', field.validationMessage !== '' ? 'true' : 'false');
267
+ }
265
268
  setError(prev => {
266
269
  var _prev$key;
267
270
  var prevMessage = (_prev$key = prev === null || prev === void 0 ? void 0 : prev[key]) !== null && _prev$key !== void 0 ? _prev$key : '';
@@ -316,21 +319,26 @@ function useFieldset(ref, config) {
316
319
  var field = {
317
320
  config: _rollupPluginBabelHelpers.objectSpread2({
318
321
  name: fieldsetConfig.name ? "".concat(fieldsetConfig.name, ".").concat(key) : key,
319
- form: fieldsetConfig.form,
320
322
  defaultValue: uncontrolledState.defaultValue[key],
321
323
  initialError: uncontrolledState.initialError[key]
322
324
  }, constraint),
323
325
  error: (_error$key = error === null || error === void 0 ? void 0 : error[key]) !== null && _error$key !== void 0 ? _error$key : ''
324
326
  };
327
+ if (fieldsetConfig.form) {
328
+ field.config.form = fieldsetConfig.form;
329
+ field.config.id = "".concat(fieldsetConfig.form, "-").concat(field.config.name);
330
+ field.config.errorId = "".concat(field.config.id, "-error");
331
+ }
325
332
  return field;
326
333
  }
327
334
  });
328
335
  }
336
+
329
337
  /**
330
338
  * Returns a list of key and config, with a group of helpers
331
339
  * configuring buttons for list manipulation
332
340
  *
333
- * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usefieldlist
341
+ * @see https://conform.guide/api/react#usefieldlist
334
342
  */
335
343
  function useFieldList(ref, config) {
336
344
  var configRef = react.useRef(config);
@@ -361,41 +369,6 @@ function useFieldList(ref, config) {
361
369
  var _config$defaultValue3;
362
370
  return Object.entries((_config$defaultValue3 = config.defaultValue) !== null && _config$defaultValue3 !== void 0 ? _config$defaultValue3 : [undefined]);
363
371
  });
364
- var list = entries.map((_ref3, index) => {
365
- var [key, defaultValue] = _ref3;
366
- return {
367
- key,
368
- error: error[index],
369
- config: {
370
- name: "".concat(config.name, "[").concat(index, "]"),
371
- form: config.form,
372
- defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
373
- initialError: uncontrolledState.initialError[index]
374
- }
375
- };
376
- });
377
-
378
- /***
379
- * This use proxy to capture all information about the command and
380
- * have it encoded in the value.
381
- */
382
- var command = new Proxy({}, {
383
- get(_target, type) {
384
- return function () {
385
- var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
386
- return {
387
- name: 'conform/list',
388
- value: JSON.stringify({
389
- type,
390
- scope: config.name,
391
- payload
392
- }),
393
- form: config.form,
394
- formNoValidate: true
395
- };
396
- };
397
- }
398
- });
399
372
  react.useEffect(() => {
400
373
  configRef.current = config;
401
374
  });
@@ -492,16 +465,31 @@ function useFieldList(ref, config) {
492
465
  document.removeEventListener('reset', resetHandler);
493
466
  };
494
467
  }, [ref]);
495
- return [list,
496
- // @ts-expect-error proxy type
497
- command];
468
+ return entries.map((_ref3, index) => {
469
+ var [key, defaultValue] = _ref3;
470
+ var fieldConfig = {
471
+ name: "".concat(config.name, "[").concat(index, "]"),
472
+ defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
473
+ initialError: uncontrolledState.initialError[index]
474
+ };
475
+ if (config.form) {
476
+ fieldConfig.form = config.form;
477
+ fieldConfig.id = "".concat(config.form, "-").concat(config.name);
478
+ fieldConfig.errorId = "".concat(fieldConfig.id, "-error");
479
+ }
480
+ return {
481
+ key,
482
+ error: error[index],
483
+ config: fieldConfig
484
+ };
485
+ });
498
486
  }
499
487
  /**
500
488
  * Returns the properties required to configure a shadow input for validation.
501
489
  * This is particular useful when integrating dropdown and datepicker whichs
502
490
  * introduces custom input mode.
503
491
  *
504
- * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usecontrolledinput
492
+ * @see https://conform.guide/api/react#usecontrolledinput
505
493
  */
506
494
  function useControlledInput(config) {
507
495
  var _config$defaultValue4;
package/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { type FieldConfig, type FieldsetConstraint, type Submission, getFormElements, hasError, parse, shouldValidate, } from '@conform-to/dom';
1
+ export { type FieldConfig, type FieldsetConstraint, type Submission, getFormElements, hasError, list, validate, requestCommand, requestSubmit, parse, shouldValidate, } from '@conform-to/dom';
2
2
  export * from './hooks';
3
3
  export * as conform from './helpers';
package/index.js CHANGED
@@ -16,14 +16,30 @@ Object.defineProperty(exports, 'hasError', {
16
16
  enumerable: true,
17
17
  get: function () { return dom.hasError; }
18
18
  });
19
+ Object.defineProperty(exports, 'list', {
20
+ enumerable: true,
21
+ get: function () { return dom.list; }
22
+ });
19
23
  Object.defineProperty(exports, 'parse', {
20
24
  enumerable: true,
21
25
  get: function () { return dom.parse; }
22
26
  });
27
+ Object.defineProperty(exports, 'requestCommand', {
28
+ enumerable: true,
29
+ get: function () { return dom.requestCommand; }
30
+ });
31
+ Object.defineProperty(exports, 'requestSubmit', {
32
+ enumerable: true,
33
+ get: function () { return dom.requestSubmit; }
34
+ });
23
35
  Object.defineProperty(exports, 'shouldValidate', {
24
36
  enumerable: true,
25
37
  get: function () { return dom.shouldValidate; }
26
38
  });
39
+ Object.defineProperty(exports, 'validate', {
40
+ enumerable: true,
41
+ get: function () { return dom.validate; }
42
+ });
27
43
  exports.useControlledInput = hooks.useControlledInput;
28
44
  exports.useFieldList = hooks.useFieldList;
29
45
  exports.useFieldset = hooks.useFieldset;
package/module/helpers.js CHANGED
@@ -1,6 +1,8 @@
1
1
  function input(config) {
2
+ var _config$initialError;
2
3
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3
4
  var attributes = {
5
+ id: config.id,
4
6
  type: options.type,
5
7
  name: config.name,
6
8
  form: config.form,
@@ -11,7 +13,9 @@ function input(config) {
11
13
  max: config.max,
12
14
  step: config.step,
13
15
  pattern: config.pattern,
14
- multiple: config.multiple
16
+ multiple: config.multiple,
17
+ 'aria-invalid': Boolean((_config$initialError = config.initialError) === null || _config$initialError === void 0 ? void 0 : _config$initialError.length),
18
+ 'aria-describedby': config.errorId
15
19
  };
16
20
  if (config.initialError && config.initialError.length > 0) {
17
21
  attributes.autoFocus = true;
@@ -26,13 +30,16 @@ function input(config) {
26
30
  return attributes;
27
31
  }
28
32
  function select(config) {
29
- var _config$defaultValue;
33
+ var _config$defaultValue, _config$initialError2;
30
34
  var attributes = {
35
+ id: config.id,
31
36
  name: config.name,
32
37
  form: config.form,
33
38
  defaultValue: config.multiple ? Array.isArray(config.defaultValue) ? config.defaultValue : [] : "".concat((_config$defaultValue = config.defaultValue) !== null && _config$defaultValue !== void 0 ? _config$defaultValue : ''),
34
39
  required: config.required,
35
- multiple: config.multiple
40
+ multiple: config.multiple,
41
+ 'aria-invalid': Boolean((_config$initialError2 = config.initialError) === null || _config$initialError2 === void 0 ? void 0 : _config$initialError2.length),
42
+ 'aria-describedby': config.errorId
36
43
  };
37
44
  if (config.initialError && config.initialError.length > 0) {
38
45
  attributes.autoFocus = true;
@@ -40,15 +47,18 @@ function select(config) {
40
47
  return attributes;
41
48
  }
42
49
  function textarea(config) {
43
- var _config$defaultValue2;
50
+ var _config$defaultValue2, _config$initialError3;
44
51
  var attributes = {
52
+ id: config.id,
45
53
  name: config.name,
46
54
  form: config.form,
47
55
  defaultValue: "".concat((_config$defaultValue2 = config.defaultValue) !== null && _config$defaultValue2 !== void 0 ? _config$defaultValue2 : ''),
48
56
  required: config.required,
49
57
  minLength: config.minLength,
50
58
  maxLength: config.maxLength,
51
- autoFocus: Boolean(config.initialError)
59
+ autoFocus: Boolean(config.initialError),
60
+ 'aria-invalid': Boolean((_config$initialError3 = config.initialError) === null || _config$initialError3 === void 0 ? void 0 : _config$initialError3.length),
61
+ 'aria-describedby': config.errorId
52
62
  };
53
63
  if (config.initialError && config.initialError.length > 0) {
54
64
  attributes.autoFocus = true;