aforemny / material-components-web-elm

Material Components for Elm
https://aforemny.github.io/material-components-web-elm
MIT License
93 stars 21 forks source link

Browser autofill - name attribute on native inputs #153

Open nunntom opened 2 years ago

nunntom commented 2 years ago

Thanks for the great package.

How to deal with browser autofill/autocomplete? There doesn't seem to be a way to give the native inputs a name or id attribute, only attributes applied to the custom element wrapper. How do we prompt the browser to give helpful suggestions? It would be useful to be able to give attributes to the inputs.

aforemny commented 2 years ago

Hi @nunntom, I think it should be sufficient to add TextField.setAutoComplete : List String -> Config -> Config (and similar for TextArea and Select) and then have the implementation use that for the autocomplete attribute on the TextFields input node.

What do you think?

Looking at https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete it says:

Note: In order to provide autocompletion, user-agents might require input/select/textarea elements to:

  • Have a name and/or id attribute
  • Be descendants of a form element
  • The form to have a submit button

I don't understand that and I likely wouldn't want to implement anything like that unless I know why it is absolutely necessary. As far as I can tell, autocomplete on inputs (etc) should suffice, no?

Is this something you would like to attempt? Otherwise I might get around doing that at some point. :-)

References

nunntom commented 2 years ago

Thanks @aforemny.

It seems there are two distinct behaviours confusingly often called either autocomplete or auto-fill.

  1. The browser remembers anything you type into an input along with the input's name/id attribute and then suggests previous entries to you the next time an input has the same name/id, regardless what that name or id is. In Chrome this is under "browsing data" and in Firefox "history".
  2. You can opt to store your name, address, contact and password information in the browser and these can be auto-filled in for you on contact forms. This is called Auto-Fill in Chrome settings and confusingly relates to the autocomplete attribute which helps the browser figure out which field is which, although if the autocomplete attribute is not present it can also use the name attribute to do this. In Firefox Autofill is currently only available in en-US builds - I don't have it in mine: https://support.mozilla.org/en-US/kb/automatically-fill-your-address-web-forms#firefox:linux:fx96

Ideally being able to set the name and the autocomplete attributes would cover both.

I can do this for TextField and TextArea. I don't think so for Select as it is not a native element and I can't find any documentation for this on the MDC select. For my use case TextField and TextArea is enough.

aforemny commented 2 years ago

It seems there are two distinct behaviours confusingly often called either autocomplete or auto-fill.

Thanks for elaborating! I'm assuming 1. refers to autofill while 2. is autocomplete.

1. The browser remembers anything you type into an input along with the input's name/id attribute and then suggests previous entries to you the next time an input has the same name/id, regardless what that name or id is. In Chrome this is under "browsing data" and in Firefox "history".

Interesting, so that might relate to the input in addition having to be in a form. Would you happen to know where that exact behavior is specified? Where does it say that it has to be name or id (which takes preference?) and cannot be anything else? I am not in favor of adding name or id configuration to input elements, as that has a long history in web programming which is not all that adequate for Elm.

Does the name, id combination depend on what else? form id if present? Exact URL? Origin URL?

2. You can opt to store your name, address, contact and password information in the browser and these can be auto-filled in for you on contact forms. This is called Auto-Fill in Chrome settings and confusingly relates to the autocomplete attribute which helps the browser figure out which field is which, although if the autocomplete attribute is not present it can also use the name attribute to do this. In Firefox Autofill is currently only available in en-US builds - I don't have it in mine:
   https://support.mozilla.org/en-US/kb/automatically-fill-your-address-web-forms#firefox:linux:fx96

Ideally being able to set the name and the autocomplete attributes would cover both.

I can do this for TextField and TextArea. I don't think so for Select as it is not a native element and I can't find any documentation for this on the MDC select. For my use case TextField and TextArea is enough.

Contrary to functions setName and setId, I would be in favor of adding setAutocomplete. Too bad it is not (yet) supported in non-en-US builds.

However, the fact that select is not wrapping a native element anymore, this makes me wary: it feels incomplete that setAutocomplete would then not be available for select as at is an essential form input IMO. Additionally, what if MDC Web (upstream) makes it a native element again? What if MDC Web decides to make text area not a native element anymore. Is there some documentation of auto-fill/ autocomplete available at MDC Web? Then we could rely on some stability there, and also that could influence our decisions.

Alternatively, I would also be OK to add setNativeAttributes to relevant components, analog to setAttributes, but applied to the native element if they are warpping one. We have to caution on some restrictions, but then setting name, id and autocomplete on text inputs would be entirely feasible.

That would be a general escape hatch for both issues, without us having to maintain auto-fill/ auto-complete support. As I said, I would be up for maintaining such an interface, but I feel the following has to be evaluated before:

nunntom commented 2 years ago

Thanks for elaborating! I'm assuming 1. refers to autofill while 2. is autocomplete.

The names are confusing. In Chrome and Firefox settings 2. is called autofill. 1. is not well defined.

Interesting, so that might relate to the input in addition having to be in a form. Would you happen to know where that exact behavior is specified? Where does it say that it has to be name or id (which takes preference?) and cannot be anything else?

I haven't been able to find documentation on this. I found this out mostly by experimentation. Try playing around with this jsfiddle: https://jsfiddle.net/2pef1mtx/ Depending on how your browser privacy & security settings are set up you should see different suggestions relating to the input attributes. Try submitting and running again and see how it remembers entries. In my testing a wrapping form element wasn't necessary. Needless to say consistency across browsers may be hit and miss.

A slightly out of date article but still useful: https://cloudfour.com/thinks/autofill-what-web-devs-should-know-but-dont/

Clearly 2. is the better option in the long run but not currently supported across the board including non en-US Firefox. Users may be used to 1. working in many cases.

I think setNativeAttributes would be the best solution allowing for the most flexibility and not tying it down to a particular implementation. Leave it up to the package consumer how they want to manage this but at least give them the possibility of doing it.

aforemny commented 2 years ago

Thanks for all the information. I will digest it as time permits! :-)

I think setNativeAttributes would be the best solution allowing for the most flexibility and not tying it down to a particular implementation. Leave it up to the package consumer how they want to manage this but at least give them the possibility of doing it.

OK. We can go ahead with this independent of this particular use case.

A pull request would be welcome if you feel up for it!