Form.reatomField
method isn't affected by the validation during the Form.onSubmit
callI took the example from the documentation and written a unit test for it:
// The example from the doc (https://www.reatom.dev/package/form/)
import { reatomForm } from '@reatom/form'
export const loginForm = reatomForm(
{
async onSubmit(ctx) {
const user = await api.login(ctx, {
name: ctx.get(nameField),
password: ctx.get(passwordField),
})
},
},
'loginForm',
)
export const nameField = loginForm.reatomField({ initState: '' }, 'nameField')
export const passwordField = loginForm.reatomField(
{
initState: '',
validate(ctx, { state }) {
if (state.length < 6)
throw new Error('The password should have at least six characters.')
},
},
'passwordField',
)
// My unit tests
import test from 'node:test';
import assert from 'node:assert';
import { loginForm, passwordField } from '../src/index.js';
import { createCtx } from '@reatom/framework';
test('Login form', () => {
const ctx = createCtx();
loginForm.onSubmit(ctx);
assert.strictEqual(
ctx.get(passwordField.validationAtom).error,
'The password should have at least six characters.',
);
});
The test fails. I've figured out the the password field's validate
isn't called at all during the submit.
It happens because the internal validation function expects that the field is in the fieldsListAtom
,
but a field gets into it only on the first change. The implementation:
// https://github.com/artalar/reatom/blob/v3/packages/form/src/reatomForm.ts#L146
const reatomFormField: Form['reatomField'] = (
options,
fieldName = options.name ?? __count(`${typeof options.initState}Field`),
) => {
// ...
atomField.onChange((ctx) => {
if (isInit(ctx)) {
fieldsListAtom(ctx, (list) => [...list, atomField])
}
})
// ...
}
I expect that field's validation callback is called even if the field was not changed since the initialization, because it should be possible to see validation messages even if the form was submitted without change fields values.
Field.remove
function adds another copy of the field to fieldsListAtom
// https://github.com/artalar/reatom/blob/v3/packages/form/src/reatomForm.ts#L146
const reatomFormField: Form['reatomField'] = (
options,
fieldName = options.name ?? __count(`${typeof options.initState}Field`),
) => {
// ...
atomField.remove = action((ctx) => {
fieldsListAtom(ctx, (list) => [...list, atomField]) // <- it should filter out the atomField
}, `${fieldName}.remove`)
// ...
}
Package @reatom/form
3.3.2
No response
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too