T
TanStack3mo ago
future-harlequin

linked fields, source field validation uses stale linked values

i have this linked field logic, and for some reason i can't figure out how to get the validation trigger to use the newly set values. i'm able to get around this by, instead of using linked fields, in the source field i just manually set the values there. everything works great then, but it's a bit unergonomic because this is an array field, so i have to manually iterate over each array entry and setFieldValue
<form.api.AppField
key={split.memberUserId + view.value}
name={`splits[${index}].${view.value}`}
validators={{
onChangeListenTo: ["amount"],
onChange: (context) => {
if (view.value === "percent") {
const percent =
splitFieldContext.state.value.percent;
const total =
splitFieldContext.form.state.values.amount;

const updateFn = updateSplit({
key: "percent",
value: percent,
total: total
});

splitFieldContext.setValue(updateFn);
}
// seemingly no matter how i trigger validation here,
// the values set above ^ are not used during validation
// although i see updated values in form state and ui
form.validateSomehowOrAnother()
},
}}
children={(fieldContext) => (
<div key={view.value} className="space-y-2"><fieldContext.SheetSplitField ... /></div>
)}
/>
<form.api.AppField
key={split.memberUserId + view.value}
name={`splits[${index}].${view.value}`}
validators={{
onChangeListenTo: ["amount"],
onChange: (context) => {
if (view.value === "percent") {
const percent =
splitFieldContext.state.value.percent;
const total =
splitFieldContext.form.state.values.amount;

const updateFn = updateSplit({
key: "percent",
value: percent,
total: total
});

splitFieldContext.setValue(updateFn);
}
// seemingly no matter how i trigger validation here,
// the values set above ^ are not used during validation
// although i see updated values in form state and ui
form.validateSomehowOrAnother()
},
}}
children={(fieldContext) => (
<div key={view.value} className="space-y-2"><fieldContext.SheetSplitField ... /></div>
)}
/>
13 Replies
unwilling-turquoise
unwilling-turquoise3mo ago
I'm not sure I understand what you're trying to do. You want to change the value of a different field that is being validated? And do that transform before it is validated?
future-harlequin
future-harlequinOP3mo ago
field a changes field b changes based on the change to field a (I thought this is the point of linked fields) form is validated after both of ^ are finished, so we're validating on the most recent state
unwilling-turquoise
unwilling-turquoise3mo ago
well, you have two ways to go about it: 1. use listeners for changing field b, you can attach it to field a if it's easier to follow the logic this way. Then call form.validateField('b', 'change') to trigger the validation (until this PR is merged). Field b will simply have an onChange validator. 2. in field b, use onChangeListenTo to listen to a. On change, transform the value and validate using that output.
future-harlequin
future-harlequinOP3mo ago
I think in the snippet above (2) is what i'm doing but i can't get the form validation to work in (2). it's operating on stale values for field b when manually triggering validation
unwilling-turquoise
unwilling-turquoise3mo ago
you're affecting the value, but you're not using it in the validation you're setting to a new value, yes, but then you're not using the value you have right there to do the validation you need and you risk getting into a loop where validators for field b will end up in a cycle of setting itself so I don't recommend adding that in validators. A listener is safer
future-harlequin
future-harlequinOP3mo ago
so i don't understand what you mean that i'm not using it in the validation. when i try calling like form.validate('change'), it does validate, just on the old values for field b i do take the point that listeners is probably safer due to potential looping
unwilling-turquoise
unwilling-turquoise3mo ago
You have * Take old value * Transform to new value, const newValue * Set the new value * Validate You have access to newValue already this assumes the field validator is the concern here if it's the form validator or the like, then the listener approach should also fix this
future-harlequin
future-harlequinOP3mo ago
I need validate the field yea, but all the validation logic lives in the schema Are you saying I should manually validate rather than just calling validation on the form? Like I don’t follow the “you have access to the newValue already” piece. Why does that matter?
unwilling-turquoise
unwilling-turquoise3mo ago
it was all with the assumption that you're trying to have a field validator. The more I look at your snippet though, the more I realize that you're really just looking for listeners instead of validators let me know if the listener fixes the issue
future-harlequin
future-harlequinOP3mo ago
Ok I’ll try that. I feel like maybe this could be mentioned in linked fields docs- when I read the concept of that it sounds like what I’m looking for, but it actually likely isn’t
unwilling-turquoise
unwilling-turquoise3mo ago
yeah, it's not for this case at all. It's meant for field validators that depend on other fields. But you use a form-level schema. Every field is going to run it, so there's no reason to listen to specific ones. What you do need however is to have a side effect from one field (changing the other). So that's where listeners come in
future-harlequin
future-harlequinOP3mo ago
just getting around to this- so am i understanding correctly that the listener would go on field a? if so, what would be the reason to not just put that logic on the input itself?
unwilling-turquoise
unwilling-turquoise3mo ago
at the moment? none apart from the location of it. once the PR is merged for setFieldValue triggering the listener, that would be a notable difference.

Did you find this page helpful?