Saurabh Tiwari Saurabh Tiwari - 4 months ago 31
AngularJS Question

Angular ng-repeat updates view, but not correctly, on changing array size

I know the title of the question is familiar on SO. I went through many questions and tried their solutions but somehow I am still stuck.

Well I have an array

A
which is being repeated to form a row of input boxes. I have a got a ADD button to add a new row where I basically push a dummy element to this array (so that its length increases and one more row is displayed on UI). The data from input box is stored in the array
A
itself at row's
$index
.

Well, this all works fine. But when I remove a row (I have another button to remove it). While removing I pass the
$index
of the row and do a
splice
at that index.

What I expected was that the element at this index will be removed, which will result in removal of this row from UI. But what's really happening is:

The element gets removed from array
A
and one row gets removed from UI too. But its not the row where REMOVE button was clicked. Rather the last row is removed from UI (regardless of where you click REMOVE).

I am clueless what's going wrong ? Found various similar question, tried many things, but nothing worked :(

Below is relevant code, In this code
home
is the alias of the controller i.e.
controllerAs : home
:

<div ng-repeat= "d in home.degrees track by $index" class="inline_block name_container">
<div class="inline_block aw_div_first">
<label>College/University/Board:</label></br>
<input class="form-control pd-forms" type="text" ng-model="home['degree'][$index]['college']" placeholder="College/University/Board"/>
</div>
<div class="inline_block aw_div">
<label>Qualification:</label></br>
<input class="form-control pd-forms" type="text" ng-model="home['degree'][$index]['qual']" placeholder="Qualification"/>
</div>
<div class="inline_block aw_div">
<label>Passing Year:</label></br>
<input class="form-control pd-forms" type="text" ng-model="home['degree'][$index]['year']" placeholder="Passing Year"/>
</div>
<div class="btn btn-primary inline_block aw_button" ng-click="home.addDegree($index, home['degree'][$index])" ng-if="$index === home.degrees.length - 1">+</div>
<div class="btn btn-primary inline_block aw_button" ng-click="home.removeDegree($index)" ng-if="($index <= home.degrees.length - 1) && home.degrees.length > 1">-</div>
</div>


Controller:

vm.degrees = [1]; //initialising array with one element to show one row initially

function addDegree(i, data){
var degree ={};
degree.college = data.college;
degree.qual = data.qual;
degree.year = data.year;
vm.degrees[i] = degree;
vm.degrees.push(1);
console.log("current degrees : ", vm.degrees);
}

function removeDegree(i){
vm.degrees.splice(i,1);
}

Answer

Try this , its working.

DEMO: DEMO

 <body ng-app="plunker" ng-controller="MainCtrl as home">
    <div ng-repeat= "d in home.degrees track by $index" class="inline_block name_container">
         <div class="inline_block aw_div_first">
          <label>College/University/Board:</label><br>
          <input class="form-control pd-forms" type="text"  ng-model="d.college" placeholder="College/University/Board"/>
         </div>
         <div class="inline_block aw_div">
          <label>Qualification:</label><br>
          <input class="form-control pd-forms" type="text"  ng-model="d.qual" placeholder="Qualification"/>
         </div> 
         <div class="btn btn-primary inline_block aw_button" ng-click="home.addDegree($index, d)" ng-if="$index === home.degrees.length - 1">+</div>
         <div class="btn btn-primary inline_block aw_button" ng-click="home.removeDegree($index)" ng-if="($index <= home.degrees.length - 1) && home.degrees.length > 1">-</div>
    </div>
  </body>

JAVASCRIPT

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  var vm = this;

  vm.degrees = [{college:'a',qual:'at'},{college:'b',qual:'bt'}]; //initialising array with one element to show one row initially

vm.addDegree = function(i, data){  
console.log(data);
            var degree ={};
            degree.college = 'test';
             degree.qual = 'testq';
          //  degree.year = data.year;
          //  vm.degrees[i] = degree;
            vm.degrees.push(degree);
            console.log("current degrees : ", vm.degrees);
        }

       vm.removeDegree = function(i){
         console.log(i);   
            vm.degrees.splice(i,1);
            console.log(vm.degrees);
        }
});