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.

when ng-maxlength is invalid, 'require' validation is also invalid #6304

Closed

Description

@homanchou

On a pristine form, I have an input field

<form name="myForm">
    <input name="username" ng-model="user.name" required ng-maxlength="5">
</form>

Given that user.name was pre-populated with a string exceeding 5 characters, in angular 1.1.5 the modelCtrl errors were:

form.username.$error = {"required":false,"maxlength":true}

That is expected because only the maxlength is violated, so 'required' was not invalid.

But after angular > 1.2.0 this behavior is now invalid for both:

form.username.$error = {"required":true,"maxlength":true}

This is a bit unexpected. Why should 'required' have an error when the model has some value... unless we're now saying that the value being required must be valid across all other validation requirements in total?

You can test it here by swapping out the angular version:
http://plnkr.co/edit/uUaC9tgHEozBkUReRXBk?p=preview

Activity

  1. caitp commented on Feb 18, 2014

    @caitp
    Contributor

    I haven't been able to sleep, so I've been trying to find the commit which broke this:

    ../input_bisect_spec.js:

    'use strict';
    
    describe('#6304', function() {
      var element;
    
      afterEach(function() {
        dealoc(element);
      });
    
      iit('should not set ngRequired error', inject(function($compile, $rootScope) {
        $rootScope.user = {
          name: "a very long value"
        };
        element = $compile('<form name="form"><input type="text" required ng-model="user.data" name="uname" ng-maxlength="5" /></form>')($rootScope);
        $rootScope.$digest();
    
        expect($rootScope.form.uname.$error.required).toBeFalsy();
      }));
    });

    ../test.sh:

    rm -rf node_modules
    rm -rf bower_components
    rm -rf components
    npm install
    grunt package
    mv test/ng/directive/inputSpec.js test/ng/directive/inputSpec_.js
    cp ../input_bisect_spec.js test/ng/directive/inputSpec.js
    grunt test:jqlite
    code=$?
    mv test/ng/directive/inputSpec_.js test/ng/directive/inputSpec.js
    exit $code

    Bisecting with:

    git bisect start v1.2.13 v1.1.4
    git bisect run ../test.sh

    But interestingly, the unit test fails ($error.required === true) for every tried commit, including the 1.1.5 commits, even though this isn't the behaviour seen in the repro.

    I'm probably doing something wrong that isn't obvious while exhausted, so maybe I'll do better tomorrow. If you want to have a go at finding the CL responsible for the change in behaviour, that would be awesome.

  2. self-assigned this
    on Feb 18, 2014
  3. tbosch commented on Feb 18, 2014

    @tbosch
    Contributor

    You mean with angular 1.1.5 you have "required":false, right?

    If you clear the input and enter the 6 characters yourself, you will get required:false, but not on the initial load. So this really seems to be a bug!

  4. added this to the milestone on Feb 18, 2014
  5. removed their assignment
    on Feb 18, 2014
  6. caitp commented on Feb 20, 2014

    @caitp
    Contributor

    @tbosch it does, but I can't seem to get this to happen in a unit test. It's a bit curious. Do you see anything wrong in the test I wrote up there?

  7. Narretz commented on Feb 27, 2014

    @Narretz
    Contributor

    It's probably caused by 31f190d or one of the other compilation fixes (maybe 4357da8)

    In 1.2.0-rc.2, the link functions run input -> required, in 1.2.0-rc.3 they run required -> input

  8. tbosch commented on Mar 4, 2014

    @tbosch
    Contributor

    @caitp Sorry for the late answer. The html to be compiled contains ng-model="user.data" but you use user.name in the JS code. Should be ng-model="user.name".

    Here is the corrected test case that also includes the manual user interaction:

    'use strict';
    
    describe('#6304', function() {
      var element;
    
      afterEach(function() {
        dealoc(element);
      });
    
      iit('should not set ngRequired error', inject(function($compile, $rootScope) {
        $rootScope.user = {
          name: "a very long value"
        };
        element = $compile('<form name="form"><input type="text" required ng-model="user.name" name="uname" ng-maxlength="5" /></form>')($rootScope);
        $rootScope.$digest();
    
        expect($rootScope.form.uname.$error.required).toBeFalsy();
    
        // simulate user interaction
        var input = element.children();
        input.val('another very long value');
        browserTrigger(input, 'change');
    
        expect($rootScope.form.uname.$error.required).toBeFalsy();
      }));
    });
    
  9. tbosch commented on Mar 4, 2014

    @tbosch
    Contributor

    While debugging this, I know why the problem exists:

    1. Initially the <input> is empty
    2. When setting a value that is too long in the scope Angular creates a validation error and does not set the value into the <input>

    By this, the value is still not present in the real DOM element, and therefore Angular says that it fails the required validation. So the problem lies in those 3 lines: https://github.com/angular/angular.js/blob/master/src/ng/directive/input.js#L1423-L1425
    In there, the required validator is called always with the view value, which is empty initially as the max length validation did not pass.

  10. caitp commented on Mar 4, 2014

    @caitp
    Contributor

    haha, well it was like 4am when I wrote that stuff, that's my excuse. Good catch @tbosch

  11. 13 remaining items

  12. removed this from the 1.3.0-beta.5 milestone on Apr 3, 2014
  13. assigned and unassigned on Apr 7, 2014
  14. modified the milestones: , 1.3.0-beta.6 on Apr 7, 2014
  15. added 3 commits that reference this issue on May 7, 2014
    41d967a
    a3b42de
    0890edb
  16. matsko commented on May 7, 2014

    @matsko
    Contributor

    @homanchou this PR should fix that: #7377

  17. added 2 commits that reference this issue on May 27, 2014
    bbcda9c
    9dbd5f5
  18. added 3 commits that reference this issue on Jun 10, 2014
    fcdd895
    ce52989
    999aa15
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