| 148 | * form submit fails with errors. |
| 149 | */ |
| 150 | export class FieldValidationState implements ValidationState { |
| 151 | constructor(readonly node: FieldNode) {} |
| 152 | |
| 153 | /** |
| 154 | * The full set of synchronous tree errors visible to this field. This includes ones that are |
| 155 | * targeted at a descendant field rather than at this field. |
| 156 | */ |
| 157 | readonly rawSyncTreeErrors: Signal<ValidationError.WithFieldTree[]> = computed( |
| 158 | () => { |
| 159 | if (this.shouldSkipValidation()) { |
| 160 | return []; |
| 161 | } |
| 162 | |
| 163 | return [ |
| 164 | ...this.node.logicNode.logic.syncTreeErrors.compute(this.node.context), |
| 165 | ...(this.node.structure.parent?.validationState.rawSyncTreeErrors() ?? []), |
| 166 | ]; |
| 167 | }, |
| 168 | {equal: shallowArrayEquals}, |
| 169 | ); |
| 170 | |
| 171 | /** |
| 172 | * The full set of synchronous errors for this field, including synchronous tree errors and |
| 173 | * submission errors. Submission errors are considered "synchronous" because they are imperatively |
| 174 | * added. From the perspective of the field state they are either there or not, they are never in a |
| 175 | * pending state. |
| 176 | */ |
| 177 | readonly syncErrors: Signal<ValidationError.WithFieldTree[]> = computed( |
| 178 | () => { |
| 179 | // Short-circuit running validators if validation doesn't apply to this field. |
| 180 | if (this.shouldSkipValidation()) { |
| 181 | return []; |
| 182 | } |
| 183 | |
| 184 | return [ |
| 185 | ...this.node.logicNode.logic.syncErrors.compute(this.node.context), |
| 186 | ...this.syncTreeErrors(), |
| 187 | ...normalizeErrors(this.node.submitState.submissionErrors()), |
| 188 | ]; |
| 189 | }, |
| 190 | {equal: shallowArrayEquals}, |
| 191 | ); |
| 192 | |
| 193 | /** |
| 194 | * Whether the field is considered valid according solely to its synchronous validators. |
| 195 | * Errors resulting from a previous submit attempt are also considered for this state. |
| 196 | */ |
| 197 | readonly syncValid: Signal<boolean> = computed(() => { |
| 198 | // Short-circuit checking children if validation doesn't apply to this field. |
| 199 | if (this.shouldSkipValidation()) { |
| 200 | return true; |
| 201 | } |
| 202 | |
| 203 | return this.node.structure.reduceChildren( |
| 204 | this.syncErrors().length === 0, |
| 205 | (child, value) => value && child.validationState.syncValid(), |
| 206 | shortCircuitFalse, |
| 207 | ); |
nothing calls this directly
no test coverage detected
searching dependent graphs…