or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration-rules.mdcore-validation.mdfield-management.mdform-actions.mdform-management.mdindex.mdstate-access.mdvue-components.md

state-access.mddocs/

0

# State Access

1

2

Composables for accessing reactive form and field state information. These composables provide read-only access to various aspects of form and field state for reactive UI updates and conditional logic.

3

4

## Capabilities

5

6

### Field State Access

7

8

#### useFieldValue Composable

9

10

Gets reactive access to a field's current value.

11

12

```typescript { .api }

13

/**

14

* Gets reactive access to a field's current value

15

* @param path - Field path (uses injected field context if omitted)

16

* @returns Computed ref to field value

17

*/

18

function useFieldValue<TValue = unknown>(path?: MaybeRefOrGetter<string>): ComputedRef<TValue | undefined>;

19

```

20

21

#### useFieldError Composable

22

23

Gets reactive access to a field's error message.

24

25

```typescript { .api }

26

/**

27

* Gets reactive access to a field's error message

28

* @param path - Field path (uses injected field context if omitted)

29

* @returns Computed ref to field error message

30

*/

31

function useFieldError(path?: MaybeRefOrGetter<string>): ComputedRef<string | undefined>;

32

```

33

34

**Field State Examples:**

35

36

```typescript

37

import { useFieldValue, useFieldError, useField } from "vee-validate";

38

39

// Using with explicit path

40

const email = useFieldValue('email');

41

const emailError = useFieldError('email');

42

43

// Using within field context (path omitted)

44

const EmailField = {

45

setup() {

46

const field = useField('email', 'required|email');

47

48

// These will automatically use the 'email' field context

49

const value = useFieldValue(); // Same as field.value

50

const error = useFieldError(); // Same as field.errorMessage

51

52

return { value, error };

53

}

54

};

55

56

// Reactive field path

57

const currentField = ref('username');

58

const fieldValue = useFieldValue(currentField);

59

const fieldError = useFieldError(currentField);

60

61

// Watch field changes

62

watchEffect(() => {

63

console.log(`${currentField.value} value:`, fieldValue.value);

64

if (fieldError.value) {

65

console.log(`${currentField.value} error:`, fieldError.value);

66

}

67

});

68

69

// Computed properties based on field state

70

const isEmailValid = computed(() => {

71

const emailVal = useFieldValue('email');

72

const emailErr = useFieldError('email');

73

return emailVal.value && !emailErr.value;

74

});

75

```

76

77

### Form State Access

78

79

#### useFormValues Composable

80

81

Gets reactive access to all form values.

82

83

```typescript { .api }

84

/**

85

* Gets reactive access to all form values

86

* @returns Computed ref to form values object

87

*/

88

function useFormValues<TValues extends GenericObject = GenericObject>(): ComputedRef<Partial<TValues>>;

89

```

90

91

#### useFormErrors Composable

92

93

Gets reactive access to all form errors.

94

95

```typescript { .api }

96

/**

97

* Gets reactive access to all form errors

98

* @returns Computed ref to form errors object

99

*/

100

function useFormErrors<TValues extends GenericObject = GenericObject>(): ComputedRef<FormErrors<TValues>>;

101

102

type FormErrors<TValues extends GenericObject> = Partial<Record<Path<TValues> | '', string | undefined>>;

103

```

104

105

**Form State Examples:**

106

107

```typescript

108

import { useFormValues, useFormErrors, useForm } from "vee-validate";

109

110

// Setup form context

111

const { handleSubmit } = useForm();

112

113

// Access form state

114

const formValues = useFormValues();

115

const formErrors = useFormErrors();

116

117

// Watch form changes

118

watchEffect(() => {

119

console.log('Current form values:', formValues.value);

120

console.log('Current form errors:', formErrors.value);

121

});

122

123

// Computed properties based on form state

124

const hasErrors = computed(() => {

125

return Object.keys(formErrors.value).length > 0;

126

});

127

128

const formDataSummary = computed(() => {

129

const values = formValues.value;

130

return {

131

fieldCount: Object.keys(values).length,

132

filledFields: Object.values(values).filter(v => v !== '' && v != null).length,

133

hasData: Object.values(values).some(v => v !== '' && v != null)

134

};

135

});

136

137

// Form validation summary

138

const validationSummary = computed(() => {

139

const errors = formErrors.value;

140

const errorFields = Object.keys(errors).filter(key => errors[key]);

141

142

return {

143

isValid: errorFields.length === 0,

144

errorCount: errorFields.length,

145

errorFields,

146

firstError: errorFields.length > 0 ? errors[errorFields[0]] : null

147

};

148

});

149

```

150

151

### Validation State Access

152

153

#### useIsFieldDirty Composable

154

155

Checks if field value differs from initial value.

156

157

```typescript { .api }

158

/**

159

* Checks if field value differs from initial value

160

* @param path - Field path (uses injected field context if omitted)

161

* @returns Computed ref to field dirty state

162

*/

163

function useIsFieldDirty(path?: MaybeRefOrGetter<string>): ComputedRef<boolean>;

164

```

165

166

#### useIsFieldTouched Composable

167

168

Checks if field has been interacted with.

169

170

```typescript { .api }

171

/**

172

* Checks if field has been interacted with

173

* @param path - Field path (uses injected field context if omitted)

174

* @returns Computed ref to field touched state

175

*/

176

function useIsFieldTouched(path?: MaybeRefOrGetter<string>): ComputedRef<boolean>;

177

```

178

179

#### useIsFieldValid Composable

180

181

Checks if field passes validation.

182

183

```typescript { .api }

184

/**

185

* Checks if field passes validation

186

* @param path - Field path (uses injected field context if omitted)

187

* @returns Computed ref to field valid state

188

*/

189

function useIsFieldValid(path?: MaybeRefOrGetter<string>): ComputedRef<boolean>;

190

```

191

192

**Field Validation State Examples:**

193

194

```typescript

195

import {

196

useIsFieldDirty,

197

useIsFieldTouched,

198

useIsFieldValid,

199

useField

200

} from "vee-validate";

201

202

// Field state composables with explicit paths

203

const isEmailDirty = useIsFieldDirty('email');

204

const isEmailTouched = useIsFieldTouched('email');

205

const isEmailValid = useIsFieldValid('email');

206

207

// Combined field state checks

208

const emailFieldStatus = computed(() => {

209

if (!isEmailTouched.value) return 'untouched';

210

if (!isEmailValid.value) return 'invalid';

211

if (isEmailDirty.value) return 'modified';

212

return 'valid';

213

});

214

215

// Using within field context

216

const EmailField = {

217

setup() {

218

useField('email', 'required|email');

219

220

const isDirty = useIsFieldDirty();

221

const isTouched = useIsFieldTouched();

222

const isValid = useIsFieldValid();

223

224

const showValidationIcon = computed(() => {

225

return isTouched.value && (isValid.value || !isValid.value);

226

});

227

228

const fieldClasses = computed(() => ({

229

'field-untouched': !isTouched.value,

230

'field-dirty': isDirty.value,

231

'field-valid': isTouched.value && isValid.value,

232

'field-invalid': isTouched.value && !isValid.value

233

}));

234

235

return {

236

isDirty,

237

isTouched,

238

isValid,

239

showValidationIcon,

240

fieldClasses

241

};

242

}

243

};

244

245

// Reactive field paths

246

const activeField = ref('username');

247

const isActiveFieldDirty = useIsFieldDirty(activeField);

248

const isActiveFieldValid = useIsFieldValid(activeField);

249

250

// Watch state changes

251

watch([isActiveFieldDirty, isActiveFieldValid], ([dirty, valid]) => {

252

console.log(`${activeField.value} state:`, { dirty, valid });

253

});

254

```

255

256

### Form Validation State Access

257

258

#### useIsFormDirty Composable

259

260

Checks if any form field is dirty.

261

262

```typescript { .api }

263

/**

264

* Checks if any form field is dirty

265

* @returns Computed ref to form dirty state

266

*/

267

function useIsFormDirty(): ComputedRef<boolean>;

268

```

269

270

#### useIsFormTouched Composable

271

272

Checks if any form field is touched.

273

274

```typescript { .api }

275

/**

276

* Checks if any form field is touched

277

* @returns Computed ref to form touched state

278

*/

279

function useIsFormTouched(): ComputedRef<boolean>;

280

```

281

282

#### useIsFormValid Composable

283

284

Checks if entire form is valid.

285

286

```typescript { .api }

287

/**

288

* Checks if entire form is valid

289

* @returns Computed ref to form valid state

290

*/

291

function useIsFormValid(): ComputedRef<boolean>;

292

```

293

294

#### useIsSubmitting Composable

295

296

Checks if form is currently submitting.

297

298

```typescript { .api }

299

/**

300

* Checks if form is currently submitting

301

* @returns Computed ref to form submitting state

302

*/

303

function useIsSubmitting(): ComputedRef<boolean>;

304

```

305

306

#### useIsValidating Composable

307

308

Checks if form is currently validating.

309

310

```typescript { .api }

311

/**

312

* Checks if form is currently validating

313

* @returns Computed ref to form validating state

314

*/

315

function useIsValidating(): ComputedRef<boolean>;

316

```

317

318

**Form Validation State Examples:**

319

320

```typescript

321

import {

322

useIsFormDirty,

323

useIsFormTouched,

324

useIsFormValid,

325

useIsSubmitting,

326

useIsValidating,

327

useForm

328

} from "vee-validate";

329

330

// Setup form

331

const { handleSubmit } = useForm();

332

333

// Form state composables

334

const isFormDirty = useIsFormDirty();

335

const isFormTouched = useIsFormTouched();

336

const isFormValid = useIsFormValid();

337

const isSubmitting = useIsSubmitting();

338

const isValidating = useIsValidating();

339

340

// Combined form state

341

const formState = computed(() => ({

342

dirty: isFormDirty.value,

343

touched: isFormTouched.value,

344

valid: isFormValid.value,

345

submitting: isSubmitting.value,

346

validating: isValidating.value

347

}));

348

349

// Form status computed properties

350

const canSubmit = computed(() => {

351

return isFormValid.value && !isSubmitting.value && !isValidating.value;

352

});

353

354

const showUnsavedWarning = computed(() => {

355

return isFormDirty.value && !isSubmitting.value;

356

});

357

358

const formStatus = computed(() => {

359

if (isSubmitting.value) return 'submitting';

360

if (isValidating.value) return 'validating';

361

if (!isFormTouched.value) return 'pristine';

362

if (!isFormValid.value) return 'invalid';

363

if (isFormDirty.value) return 'modified';

364

return 'valid';

365

});

366

367

// Button states based on form state

368

const submitButtonProps = computed(() => ({

369

disabled: !canSubmit.value,

370

loading: isSubmitting.value,

371

text: isSubmitting.value ? 'Submitting...' : 'Submit'

372

}));

373

374

const resetButtonProps = computed(() => ({

375

disabled: !isFormDirty.value || isSubmitting.value,

376

visible: isFormDirty.value

377

}));

378

379

// Form progress indicator

380

const formProgress = computed(() => {

381

const touched = isFormTouched.value;

382

const valid = isFormValid.value;

383

const dirty = isFormDirty.value;

384

385

if (!touched) return { step: 0, label: 'Start filling the form' };

386

if (!valid) return { step: 1, label: 'Fix validation errors' };

387

if (dirty) return { step: 2, label: 'Ready to submit' };

388

return { step: 3, label: 'Form completed' };

389

});

390

391

// Watch form state changes

392

watchEffect(() => {

393

if (showUnsavedWarning.value) {

394

// Show browser warning about unsaved changes

395

window.addEventListener('beforeunload', handleBeforeUnload);

396

} else {

397

window.removeEventListener('beforeunload', handleBeforeUnload);

398

}

399

});

400

401

const handleBeforeUnload = (e: BeforeUnloadEvent) => {

402

e.preventDefault();

403

e.returnValue = 'You have unsaved changes. Are you sure you want to leave?';

404

return e.returnValue;

405

};

406

```

407

408

### Advanced State Access Patterns

409

410

#### Custom State Selectors

411

412

Creating custom computed properties based on multiple state sources.

413

414

```typescript

415

import {

416

useFormValues,

417

useFormErrors,

418

useIsFormValid,

419

useIsFormDirty

420

} from "vee-validate";

421

422

// Custom selectors

423

const formValues = useFormValues();

424

const formErrors = useFormErrors();

425

const isFormValid = useIsFormValid();

426

const isFormDirty = useIsFormDirty();

427

428

// Complex state selectors

429

const formCompleteness = computed(() => {

430

const values = formValues.value;

431

const requiredFields = ['name', 'email', 'phone'];

432

const filledRequired = requiredFields.filter(field => values[field]).length;

433

434

return {

435

percentage: (filledRequired / requiredFields.length) * 100,

436

filledFields: filledRequired,

437

totalRequired: requiredFields.length,

438

isComplete: filledRequired === requiredFields.length

439

};

440

});

441

442

const validationSummary = computed(() => {

443

const errors = formErrors.value;

444

const errorEntries = Object.entries(errors).filter(([_, error]) => error);

445

446

return {

447

hasErrors: errorEntries.length > 0,

448

errorCount: errorEntries.length,

449

fields: errorEntries.map(([field, error]) => ({ field, error })),

450

severity: errorEntries.length > 3 ? 'high' : errorEntries.length > 0 ? 'medium' : 'none'

451

};

452

});

453

454

const formHealthScore = computed(() => {

455

const valid = isFormValid.value;

456

const dirty = isFormDirty.value;

457

const completeness = formCompleteness.value.percentage;

458

const errors = validationSummary.value.errorCount;

459

460

let score = 0;

461

if (valid) score += 40;

462

if (completeness > 80) score += 30;

463

if (dirty && valid) score += 20;

464

if (errors === 0) score += 10;

465

466

return {

467

score,

468

grade: score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : 'D',

469

status: score >= 90 ? 'excellent' : score >= 80 ? 'good' : score >= 70 ? 'fair' : 'poor'

470

};

471

});

472

```