--- title: Form Labels and Error Announcements impact: HIGH impactDescription: Essential for screen reader users tags: accessibility, a11y, forms, aria-live --- ## Form Labels and Error Announcements All form inputs must have associated labels, and validation errors should be announced to screen readers using ARIA live regions. **Incorrect (missing labels and announcements):** ```glimmer-js // app/components/form.gjs ``` **Correct (with labels and announcements):** ```glimmer-js // app/components/form.gjs ``` **For complex forms, use platform-native validation with custom logic:** ```glimmer-js // app/components/user-form.gjs import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { on } from '@ember/modifier'; class UserForm extends Component { @tracked errorMessages = {}; validateEmail = (event) => { // Custom business logic validation const input = event.target; const value = input.value; if (!value) { input.setCustomValidity('Email is required'); return false; } if (!input.validity.valid) { input.setCustomValidity('Must be a valid email'); return false; } // Additional custom validation (e.g., check if email is already taken) if (value === 'taken@example.com') { input.setCustomValidity('This email is already registered'); return false; } input.setCustomValidity(''); return true; }; handleSubmit = async (event) => { event.preventDefault(); const form = event.target; // Run custom validations const emailInput = form.querySelector('[name="email"]'); const fakeEvent = { target: emailInput }; this.validateEmail(fakeEvent); // Use native validation check if (!form.checkValidity()) { form.reportValidity(); return; } const formData = new FormData(form); await this.args.onSubmit(formData); }; } ``` Always associate labels with inputs and announce dynamic changes to screen readers using aria-live regions. Reference: [Ember Accessibility - Application Considerations](https://guides.emberjs.com/release/accessibility/application-considerations/)