Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form validation not being updated when item is removed from the model. Bug?

I started using AngularJS lately, and I think I ran into a weird bug.


First, here's some working code:

View:

<body ng-controller="MainCtrl">

    <form name="form">

        <div ng-repeat="phone in phoneNumbers">
            <input ng-model="phone.number" required />
            <button ng-click="deleteNumber($index)">Delete Number</button>
        </div>

        <button ng-click="addNumber()">Add Number</button>

        <input type="submit" ng-disabled="form.$invalid" />

    </form>

</body>

Controller:

app.controller('MainCtrl', function ( $scope ) {

    $scope.phoneNumbers = [{
        number: '212-123-4567'
    }];

    $scope.addNumber = function () {
        $scope.phoneNumbers.push({
            number: ''
        });
    };

    $scope.deleteNumber = function ( index ) {
        $scope.phoneNumbers.splice(index, 1);
    };

});

Here's the Plunkr: Working example.

I think the code is pretty straightforward: there's an ng-repeat displaying every phone number, which you can edit/delete. If a phone number is added, it can't be empty; the submit button will be disabled if there's an empty phone number.


The issue arises when the submit button is placed above the ng-repeat. If you add a phone number, leave it empty, and then delete it, the submit button will stay disabled:

<body ng-controller="MainCtrl">

    <form name="form">

        <input type="submit" ng-disabled="form.$invalid" />

        <div ng-repeat="phone in phoneNumbers">
            <input ng-model="phone.number" required />
            <button ng-click="deleteNumber($index)">Delete Number</button>
        </div>

        <button ng-click="addNumber()">Add Number</button>

    </form>

</body>

Here's the plunkr: Broken example.


I love AngularJS, but this has nearly driven me insane. I've spent upwards of 20 hours chasing this stupid bug. Since a usual demo has the submit button on the bottom, I couldn't reproduce the issue. I had to take my actual code, and slowly reduce the code to the barest minimum. It is a very large and complex app, and... Well, I'll stop whining now.

My question is two-fold:

  1. Is this a bug? I even tried this with the unstable branch (1.1.3), and it works the exact same way.

  2. What can I do to work around it, without changing source order. I know I can move around my submit button via CSS, but in my case that's not really an option; I need the submit button to be the first thing in the form.


P.S. Here's a video of it in action.

like image 388
Joseph Silber Avatar asked Mar 03 '13 23:03

Joseph Silber


1 Answers

Apparently this is an active bug.

See https://github.com/angular/angular.js/issues/1572

In that bug, a workaround was posted which uses a hidden counter that is incremented when fields are added/removed - this is used to force Angular to re-validate the form.

An example jsFiddle was given: http://jsfiddle.net/HhcXT/

In template:

<input type="hidden" ng-bind="abc" />

In controller:

$scope.removeYears = function(item) {
    var index = $.inArray(item, $scope.years)
    $scope.years.splice(index, 1);        //remove element
    $scope.abc += 1;
}
like image 138
Alex Osborn Avatar answered Oct 07 '22 15:10

Alex Osborn