Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

input[type=date] borks model on binding if ngRequired is falsey #9996

Closed

Description

@EverPresent

So this wasn't a problem in the previous version of angular that I was running (1.2.*?) but as soon as I upgraded to 1.3.1 all of my required date input types would set my model value to null upon binding (which would fire my $watches prematurely and cause havok).

It seems there have been a lot of input controller related issues arise in 1.3 but looking through the open issues I don't think this one has any related.

Check out this plunk to verify the issue:
http://plnkr.co/edit/dgsiLXD4OTDt19FF6pmi?p=info

I tracked down the problem to the default formatter that is attached to the input in input.js:createDateInputType. It is returning an empty string if the value evaluates to isEmpty. Looking at other formatters the rule of thumb seems to be to return the original value that evaluated to falsey (not change it to empty string). I made this one line change and if you click the "see fixed version" at the bottom of the plunk you will see the exact same page using my fixed version of the angular.js file.

Activity

  1. Narretz commented on Nov 11, 2014

    @Narretz
    Contributor

    I think the reason for returning empty string is to have equality between $viewValue and actual DOM value. IIRC browsers that support date won't set invalid date strings as values - though that could be the case for throwing actually.

  2. added this to the milestone on Nov 11, 2014
  3. self-assigned this
    on Nov 11, 2014
  4. frfancha commented on Nov 11, 2014

    @frfancha

    Set $viewValue to '' to match DOM, why not, but then why changing the model?

  5. Narretz commented on Nov 11, 2014

    @Narretz
    Contributor

    "changing the model" is the bug

    ----- Ursprüngliche Nachricht -----
    Von: "frfancha" [email protected]
    Gesendet: ‎11.‎11.‎2014 19:46
    An: "angular/angular.js" [email protected]
    Cc: "Narretz" [email protected]
    Betreff: Re: [angular.js] input[type=date] borks model on binding ifngRequired is falsey (#9996)

    Set $viewValue to '' to match DOM, why not, but then why changing the model?
    —
    Reply to this email directly or view it on GitHub.=

  6. frfancha commented on Nov 11, 2014

    @frfancha

    Ok.

  7. EverPresent commented on Nov 12, 2014

    @EverPresent
    Author

    Mmmm... Ok, but the formatter in the stringBasedInputType function returns the original value if the value evaluates to isEmpty (which is used by input[type] text, email, and url).

    function stringBasedInputType(ctrl) {
      ctrl.$formatters.push(function(value) {
        return ctrl.$isEmpty(value) ? value : value.toString();
      });
    }
    

    As does the one in the numberInputType function (used by input[type] number).

      ctrl.$formatters.push(function(value) {
        if (!ctrl.$isEmpty(value)) {
           ... omitted for brevity ...
        }
        return value;
      });
    

    The only other built-in formatters that I found in the angular code were for checkbox and ngList which are both kind of special cases anyway.

    Is matching the DOM value something that is needed? If so, it would seem to me that these other formatters for those input types mentioned should be modified to return an empty string as well. If not, then returning the original value would seem to be an adequate fix. Thoughts?

  8. Narretz commented on Nov 12, 2014

    @Narretz
    Contributor

    @EverPresent this sounds like a good idea, actually. What makes me wonder though: when the model gets formatted to undefined instead of '', it should still get converted to null, because it is still empty. I'll have to test this again.

  9. EverPresent commented on Nov 12, 2014

    @EverPresent
    Author

    I'm playing around with this and thought I would post a little more info for your consumption.

    When the formatter receives undefined and formats it into an empty string. The parser immediately turns around and formats that empty string into null. The rest of the angular framework sees that the value of that field is set to null, and modifies the model accordingly.

    The crux of this bug, I think, is occurring when the parser converts the empty string into a null value. The rest of the angular framework is just taking that value, and doing what it is supposed to do. If the parser always converts an empty string into null, then the angular framework will always modify the underlying model (even prior to user action as we note in the above plunk) because null is a legitimate value for a bound property. If the parser always converts an empty string into undefined then the angular framework will delete the property from the model object (not necessarily what we want to happen either).

    Both null and undefined evaluate to true in isEmpty. I think the formatter must return the original value because there is a big difference between these values. If the formatter returns undefined then the parser is never called and no model-changing actions occur.

  10. frfancha commented on Nov 12, 2014

    @frfancha

    When the view has been changed by the model (=formatters have run), the parsers should not be called at all, the model must stay what it was before calling the formatters and there is no point in calling the parsers.
    The other way around is not true: when a model have been produced after a view change by the user (on blur or on each key stroke, or delayed, according to ngModelOptions), the model must be parsed to be nicely displayed, but onBlur only!
    Type 4/4/20 in date field => model is set to April, 4th 2020, but view is still 4/4/20
    The user can:
    -Leave the field: only then view is "formatted" and becomes, perhaps, 2020-04-04
    -OR: continue to type 14 => model is April, 4th, 2014, view is still 4/4/14. Only then user leaves the field => then view is "formatted" and becomes 2014-04-04 (or whatever date settings have been selected).

    Attention: this is the description of how it should behave according to me, not at all an analysis of the current behavior of AngularJS.

    Fred

  11. EverPresent commented on Nov 13, 2014

    @EverPresent
    Author

    I'm not entirely sure what the current behavior of angular is in regards to your comments. But I think you would get better feedback from the entire body of core developers if you posted those ideas on the dev mailing list or opened a separate issue to discuss proposed changes.

  12. added 3 commits that reference this issue on Nov 13, 2014
    50f7e66
    2182f8e
    dab714d
  13. Narretz commented on Nov 13, 2014

    @Narretz
    Contributor

    @frfancha
    Let's try to separate bugs from expected behavior (whether sensible or not).

    Bug:

    • Parsers running after the model is set and has been formatted

    Expected:

    • Parsers run after the viewValue is commited; this can be delayed by time or only executed on certain events, such as blur.
    • Formatters only run when the model is set from the scope. They don't run after the viewValue has been commited, parsed or set as model on the scope.
    • That means there is currently no sanctioned way of "masking" user input while / after they are entering it. Most people get around that limitation by doing that inside parsers.
  14. added 3 commits that reference this issue on Nov 15, 2014
    3ffeeb6
    ee27815
    e3764e3
  15. Narretz commented on Nov 25, 2014

    @Narretz
    Contributor

    This is fixed in 1.3.4.
    We are currently evaluating how we can make ngModel / forms better, and this includes better support for formatting, too.

  16. frfancha commented on Nov 26, 2014

    @frfancha

    @Narretz
    Thanks for the fix.

  17. weagle08 commented on Jan 23, 2015

    @weagle08

    This bug still seems to be happening in 1.3.8 & 1.3.10

  18. Narretz commented on Jan 23, 2015

    @Narretz
    Contributor

    @weagle08 I tried the plunker and it shows the same result for the latest snapshot and the fixed version that was included. If you are referring to a different error, please open a new issue. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions