Description
Background
I'm attempting to style autocomplete input field to match govuk design system recommendations. The fieldset has two conditionally revealed accessible autocomplete inputs. I would like to add extra CSS classes to the input based on whether the value of the field has failed validation or caused any errors.
Looking at the source code it would seem that there no option to set or use additional class names for custom styling. (https://github.com/alphagov/accessible-autocomplete/blob/master/src/autocomplete.js#L493-L513)
There is an existing cssNamespace
option that can set (https://github.com/alphagov/accessible-autocomplete/blob/master/src/autocomplete.js#L431-L433) but it does not allow the developer to add additional custom CSS classes to the component.
Scenario:
- The user does not select a value in the input of a required field and goes on to submit the form.
- The user enters or selects an invalid option and submits the form.
Approaches
CSS styling
I attempted to add CSS to my stylesheets to target the focus group. Unfortunately, this did not work because I had two autocomplete inputs within the same form-group and also highlights the inputs regardless as to whether they cause the error
.govuk-form-group--error .autocomplete__input {
border: $govuk-border-width-form-element-error solid $govuk-error-colour;
&:focus {
border-color: $govuk-input-border-colour;
box-shadow: none;
}
}
Attempt CSS - Incorrectly styles input whether the radio buttons are at fault
Attempt CSS - Incorrectly styles all autocompletes within a form-group that has errors
JavaScript
I also attempted to use JavaScript to clone the CSS class names of the fallback input so that it could be mirrored. For the most part, this worked but the class names were reset after the user focuses away. I could try to bind an onfocus event to the autocomplete input to add the class names back in. This is starting to feel rather hacky.
Sample of my code
const initAutocomplete = ({element, input, path}) => {
const $input = document.getElementById(input);
const $el = document.getElementById(element);
const inputValueTemplate = result => (typeof result === "string" ? result : result && result.name);
const suggestionTemplate = result =>
typeof result === "string" ? result : result && `${result.name} (${result.code})`;
try {
if($input) {
accessibleAutocomplete({
element: $el,
id: $input.id,
showNoOptionsFound: true,
name: $input.name,
defaultValue: $input.value,
minLength: 3,
source: request(path),
templates: {
inputValue: inputValueTemplate,
suggestion: suggestionTemplate
},
onConfirm: option => ($input.value = option ? option.code : ""),
confirmOnBlur: false
});
const $accessibleAutocompleteInput = $el.querySelector('.autocomplete__input');
const existingInputClasses = $input.className.split(' ')
for(let i=0; i < existingInputClasses.length; i++) {
$accessibleAutocompleteInput.classList.add(existingInputClasses[i])
}
$input.parentNode.removeChild($input);
}
} catch(err) {
console.error("Failed to initialise provider autocomplete:", err);
}
};
This sort of works until the user sets focus and then navigations to another element. It would seem as though there is another onfocus event being trigger which resets the classes
.
Conclusion
I think this component could do additionalInputCSSClassName
option that could be set when the autocomplete is initialized.
I'm happy to work on this feature if others think it would be beneficial to others and agree to it in principle. My approach would be to create a new option which if set would be added to the input when its rendered. It would not affect anything else/