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.

Different behavior for required and ng-required for initial values #9063

Closed

Description

@adharris

I'm noticing different behavior when using required vs ng-required when combined with ng-change. When the initial model value is any empty value besides undefined (i.e. null or ""), ng-changed is fired when using ng-required="true", but not when using the basic required.

It also seems that this behavior has changed from 1.3.0 rc0 and rc1. In rc0, the change handler is never called.

The behavior for ng-required in rc1 makes sense to me; validation is run for the initial value, null and "" do not pass validation so the model value is set to undefined, and sense undefined does not equal the initial value ng-change is evaluated. But shouldn't the two variants behave the same?

Here is a plunker demonstrating the differences: http://plnkr.co/edit/e1J1VnUSpR8xVhdKIXVY?p=preview

I'm not sure, but this might be related to #8949 and/or #9001

Activity

  1. Narretz commented on Sep 15, 2014

    @Narretz
    Contributor

    This is probably because ngRequired observes the required attr and fires the validation a second time.
    Actually, I don't think the behavior of ngRequired in rc.1 is correct. The validation calls the parsers, which detect an undefined viewValue and therefore changes the model value to undefined (without calling any parsers), which triggers ngChange. But as @caitp pointed out in #9044 (comment) angular should not actually parse empty input values.

  2. added this to the milestone on Sep 15, 2014
  3. caitp commented on Sep 15, 2014

    @caitp
    Contributor

    to expand on that, I don't think we should parse any values unless setViewValue was called, which should not happen when calling $validate() in isolation (imo)

  4. Narretz commented on Sep 15, 2014

    @Narretz
    Contributor

    I agree. At a minimum, running parsers should be extracted from $validate. But I haven't checked how tight the coupling overall still is.

  5. shahata commented on Sep 15, 2014

    @shahata
    Contributor

    For the record, re-parsing on $validate was introduced in tbosch@1ec8bde
    The goal was to get rid of $$invalidModelValue. If we do not want to re-parse, it means we need to add $parsedModelValue or something similar as discussed in #9016 (comment)

  6. modified the milestones: 1.3.0-rc.4, on Sep 23, 2014
  7. Narretz commented on Sep 28, 2014

    @Narretz
    Contributor

    This "fails" even with 92f05e5 (don't parse if viewValue is undefined)
    This is because there's an unnecessary validation after the model is set to the view for the first time:

    When the ngModelController is created, it checks the model via $watch, formats it, sets its viewValue, and calls $$runValidators. This is okay.
    The problem is that all directives / validators that use an observer call $validate very often, too often I'd say.
    -> before the ngModelCtrl is initialized: these are ignored because the $modelValue isn't set yet => Okay
    -> after the modelWatch is called: these go through, and since the modelValue is invalid, they set the model to undefined. Since this observer comes directly after the first model -> value, it is unnecessary, since the viewValue / modelValue cannot have changed yet.

    One solution is to not call $validate inside observers when the attr value hasn't changed. It's actually possible to that $validate is called far more often that it needs to be. The problem here is that this is needed for all observers, so everyone who writes a validator needs to be aware of this boilerplate.

  8. self-assigned this
    on Sep 29, 2014
  9. IgorMinar commented on Sep 30, 2014

    @IgorMinar
    Contributor

    @tbosch can we have a quick chat about this some time today?

  10. 23 remaining items

  11. modified the milestones: , 1.3.1 on Oct 15, 2014
  12. Narretz commented on Oct 21, 2014

    @Narretz
    Contributor

    What I don't understand (and previously didn't pay any attention to) is that required only fires the observer once, but ngRequired twice. I can for the love of it not understand why that is.

    e: it's not the cause of the issue, but it's interesting nevertheless.
    The actual cause lies somewhere here, 9ad7d74, probably something about the removal of $$invalidModelValue

  13. onehourlate commented on Nov 12, 2014

    @onehourlate

    Just to add my two cents : this change even breaks the most basic angular-only behavior with checkbox input types.

    If an input checkbox has an initial model of undefined or null, and it has both ng-required and ng-change, the ng-change callback will fire on page load, which is definitely not supposed to happen.

    cf http://plnkr.co/edit/5gqfJvtxwHpvSHoPDBfA?p=preview (the $scope.counter equals to 1 after page load, when it should be 0)

  14. Narretz commented on Nov 12, 2014

    @Narretz
    Contributor

    @btford I'm taking this over, this is part of a bigger problem with ngModel

  15. assigned and unassigned on Nov 12, 2014
  16. Narretz commented on Nov 25, 2014

    @Narretz
    Contributor

    This is fixed in 1.3.4 :)

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