Open Bug 1399046 Opened 7 years ago Updated 3 months ago

Firefox prematurely validates 'required' form fields when value is set by JavaScript

Categories

(Core :: Layout: Form Controls, defect, P3)

56 Branch
defect

Tracking

()

UNCONFIRMED
Tracking Status
firefox57 --- wontfix
firefox58 --- wontfix
firefox59 --- ?

People

(Reporter: eoghan, Unassigned)

Details

Attachments

(1 file)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36

Steps to reproduce:

With a form field which has the 'required' attribute set, on page load/page setup, set it the empty string via JavaScript.  Did not submit the form programmatically.


Actual results:

Input field was surrounded with a red box-shadow indicating the form was invalid, even though the user had not yet had a chance to enter any text.


Expected results:

Field should have only been validated when user attempts to submit the form.
Component: Untriaged → Layout: Form Controls
Product: Firefox → Core
Priority: -- → P3
I hope this can be fixed. It causes distracting red borders to appear on Angular form fields even when the user hasn't submitted or interacted with the form.

This is especially annoying when using checkboxes and frameworks such as Vue or Angular.

Vue (or its directive "v-model") sets checked to false on page load and then the user immediately sees a red checkbox. Not welcoming to users at all.

I came across this because of another bug I reported (Bug 1569314)...

Regarding this issue: The “glow” comes because of Firefox’s default CSS styles. MDN has additional info, including how to easily get rid of it.

Constraint validation has no notion of “dirty” (i.e., whether an element has received user input or not). Cf. the standard. So I don’t think a “fix” in Firefox is needed.

The desired behavior can be achieved easily with JavaScript and CSS. Otherwise, it should be a standards proposal, not a request for a browser-specific extension. :-)

Hi Florian,

I've got a feeling that you not have read through the test case fully. The test case includes Javascript which triggers the red outline (by setting it to the empty string); in fact the input field is invalid upon first pageload, as it doesn't have a value even though it is marked as requiring one. By your logic ('constraint validation has no notion of "dirty"'), the field should get the red outline upon initial page load. (If that were to be attempted of course, all of the millions of forms on the web containing a 'required' field would show up with a red outline on the field upon first presentation).

The process of validation does have state attached with it; 'before validation' which changes to either 'rejected validation' or 'accepted validation'.
This bug is recommending that javascript-only (i.e. non user) modifications to the field content don't trigger any state change from 'before validation' to 'rejected validation'.

@eoghan: I did see your test case – the JavaScript statement is a red herring (it has no effect). You can test with the following HTML. I just did in Chrome, Safari, and Firefox – they all show the red glow from the beginning. And this is exactly how the standard prescribes it.

<title>Validation for form</title>
<style>
  input:invalid {
    border: 1px solid transparent; /* without this, Safari wouldn't apply the box shadow */
    box-shadow: 0 0 1.5px 1px red; /* red glow as Firefox applies by default */
  }
</style>
<input type="text" required>

@Florian, with my apologies — I did not follow your links as I presumed you had misinterpreted.

So as I understand it now, the problem is with the -moz-ui-invalid proprietary style?
Looking at the spec for that, it seems like a more useful implementation than the more stateless standard:
https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-ui-invalid

So I guess this bug should pertain to -moz-ui-invalid only. Specifically, from the above link:
"If the element is required, the preceding rules apply only if the user has changed the value or attempted to submit the form."
When the document.getElementById('field1').value = ''; code is run, the -moz-ui-invalid pseudo class is applied even though the user has not changed the value.

So this bug should be closed either when -moz-ui-invalid is removed from Firefox, or else the -moz-ui-invalid behavior is fixed to properly detect User interaction as opposed to programmatic modification.

I believe this bug still has impact in Firefox as it results in an unexpected red box shadow appearing in circumstances where form fields need to be populated upon page load (from cache/localstorage, & whatever reason Vue/AngularJs do so).


FYI I'm sure no harm was intended, but the following statement was a little irksome in your reply:

The desired behavior can be achieved easily with JavaScript and CSS
Your use of the word 'easy' here is completely predicated on you already knowing the details, and how to override the style. A good rule of thumb is to not use the word 'easy' on the internet; 2 years ago I spent probably a few hours trying to solve this and didn't discover the distinction between :-moz-ui-invalid and :invalid (maybe it didn't exist at the time?). Resetting obscure single-browser pseudo classes should not fall into any definition of 'easy'.

@eoghan: Turns out, I need to apologize! I silently assumed :-moz-ui-invalid to be a (historic) vendor-specific version of :invalid. But as your MDN link describes, this is not the case (this wasn’t clear to me from the MDN :invalid article). BTW, for <input> elements, the relevant source code is in HTMLInputElement.h and HTMLInputElement.cpp.

So I need to add to my previous comment. The line document.getElementById('field1').value = '' in your test case does have the effect of adding pseudo-class :-moz-ui-invalid, even though it changes nothing about :invalid.

I agree with your conclusions.

...Except for one thing: I do not find -moz-ui-invalid “a more useful implementation than the more stateless standard”... After all, some sites actually do want stateless validation; i.e., even before user input. For those sites that want to wait with visualizing validation results until submit, the Bootstrap approach is “easy” (= 1 line of JavaScript in order to add a was-validated class to the form). And those sites wanting to show validation results before submit, but only after user input, can listen to change events in order to apply a class indicating “dirty”. I think in 99% of the cases, web developers are best advised to not rely on -moz-ui-invalid, and in fact to deactivate it via CSS if a uniform cross-browser experience is desired.

Thanks for your further clarification.

While I don't experience the need I agree that there's a good defensible case to be made to keep :invalid stateless (I'm sure there's no other plan to change it).

Maybe a good idea would be to get rid of -moz-ui-invalid and have the browser add those workarounds (was-validated and dirty) as pseudoclasses.

Then you could do
form:was-validated :invalid { outline: 2px solid red }
or
:invalid:dirty { outline: 2px solid orange }

And of course I'd hope that the browser would only make fields dirty if the value is actually modified by the user.

All the best!

Eoghan

Severity: normal → S3

Bug still exists in 2024.
However, instead of using :user-invalid, you could also do this as a workaround:

Bug still exists in 2024. For people looking for the issue of fields already starting as :user-invalid on page load you could also do this as a workaround:

    input:not(:placeholder-shown):not(:focus):invalid {
      color: $color-error;
      background-color: white;
      border: 1px solid $color-error;
    }
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: