Page MenuHomePhabricator

Error messages display on autofill
Closed, ResolvedPublic5 Estimated Story PointsBUG REPORT

Description

Steps to Reproduce:

  • Go to the donation page (laika Skin) with an iOS device.
  • Go to the first name field and use the autofill option

Actual Results:
All autofilled fields except the first name field show error messages

Expected Results:
Autofilled fields show they are correctly filled

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

This task was mainly investigation. Here's what I found:

The problem:
When you use autofill in the form on spenden the information is not processed correctly resulting in error messages appearing below the fields even though they are filled in correctly.
This happens only in Safari - on mobile, desktop and ipad.

The reason:
Safari's autofill (and autocomplete) action does not fire any events.

How does that affect the logic in our form Vue components:
The v-model directive doesn't work as expected, because it relies on events being fired (input event for text and change event for checkboxes and radio buttons)

What's on the Internet:
All three major frontend frameworks have an issue opened on github regarding this bug. All three of them did not incorporate any solution in their framework, since this is considered strictly browser related. If you're interested:
Vue // Autofill does not trigger change
React // Provide a way to handle browser-autocompleted form values on controlled components
Angular // Form model doesn't update on autocomplete
A popular StackOverflow thread about the same problem

Proposed solutions:

  • Some people claim wrapping the input elements in a <form> solved the problem. Our input fields are already wrapped in a form, so that's obviously not an ultimate solution.
  • Other people claim declaring name attributes to every input element also solves the problem. I did not understand why but also doesn't work for us.
  • Using this autofill library seems to work for a lot of people. Unfortunately it provides a solution only for jQuery and Angular projects.
  • Using the css selector :-webkit-autofill, specific to Safari, to expose a hook for JS when autofill happens. The solution is described here and the project where it's applied is a React one. I think this is our best shot.

What makes this even more complicated in our case:
We are using Buefy's input component <b-input>. Ideally the fix should be applied in that component.
Otherwise we have to hack this in our codebase and not forget to apply the hack on every <b-input> we use.

The hack:
Define a custom class like this

.custom-input {
	&:-webkit-autofill {
		// Expose a hook for JavaScript when auto fill is shown.
		// JavaScript can capture 'animationstart' events
		animation-name: onAutoFillStart;
	
		// Make the backgound color become yellow _really slowly_
		transition: background-color 50000s ease-in-out 0s;
	}
	
	&:not(:-webkit-autofill) {
		// Expose a hook for JS onAutoFillCancel
		// JavaScript can capture 'animationstart' events
		animation-name: onAutoFillCancel;
	}
}

Import the custom.scss into every component that uses <b-input>. Add the class custom-input to every <b-input>.
In the mounted lifecycle hook register an event listener for autofill start. On autofill start, do some logic that is usually done by the v-model directive - update the $data with the autofilled value.
What's extra unpleasant for us is that we keep the values in the store and we made the components with the input fields unaware of the store. They fire events to the parent who takes care of populating the store.

It's not the best, because it could be easily forgotten and it's not very obvious what's going on, but is the only one that works. I really think this should be solved in Buefy.

ping @Tim_WMDE and @gabriel-wmde for opinions.

p.s. I fell into a rabbit hole. Here are some other links related to events and autofill/autocomplete:
Introduction to Events
Autocomplete and JavaScript Change Event

kai.nissen changed the point value for this task from 3 to 0.Sep 16 2019, 10:18 AM
gabriel-wmde changed the point value for this task from 0 to 5.Sep 24 2019, 8:35 AM

We're keeping the same ticket for the actual fix, hence the points change. We agreed on applying the solution with the webkit specific css selector.
That entails:

  • creating a wrapper component that implements the solution
  • adding matomo tracking to that component in order to figure out how many users experience this bug
  • putting the wrapper around all <b-input> instances in our code

If we make this work and have some chunk of data showing people use safari autofill, we will open an issue/PR to Buefy to fix the problem and see if they accept it.

Successfully tested https://github.com/wmde/FundraisingFrontend/pull/1685 on iOS. Although the errors messages flash up briefly, they are subsequently removed. This behavior is caused by the need to wait for 50 milliseconds to accumulate all the autofill events and then send the accumulated values to the store.

kai.nissen claimed this task.