0

I'm creating a form that has add/remove function. To achieve that, I tried to use ng-model in ng-repeat. Here's what my code looks like.

<button ng-click='add()'>Add more</button>
<div ng-repeat='x in array track by $index'>
    <input ng-model='array[$index].name'></input>
    <input ng-model='array[$index].phone'></input>
    <input ng-model='array[$index].email'></input>
</div>

//angular module
$scope.add = function () {
    $scope.array.push(item);
};

But then, all input field will be synchronized and all the item in the array looks the same, which is what I don't intend to. Also, I made a sample of my code in codepen.

1
  • Just fyi you don't need to reference your array element by index. Use the x variable declared in your expression. That is your hook onto that specific element in each iteration. Commented Dec 15, 2016 at 21:47

3 Answers 3

2

So basically you're pushing a "item"-reference to the list every time, so you end up with a list of multiple references to one item.

You could do something like:

angular.module('myapp', [])
.controller('Ctrl', ['$scope', '$compile',function ($scope, $compile) {
  $scope.array = [];
  var item = {
    name: '',
    phone: '',
    email: '',
  };

  $scope.array.push(item);
  $scope.addItem = function () {

    $scope.array.push(
      {
        name : '',
        phone: '',
        email: '',        
      }    
    );

  };
}]);

Then it would work. A personal opinion to the html. Many people do ng-repeat like this for the sake of simplicity:

<div ng-repeat='x in array'>
    <input ng-model='x.name'></input>
    <input ng-model='x.phone'></input>
    <input ng-model='x.email'></input>
</div>
Sign up to request clarification or add additional context in comments.

Comments

1

With every push of item you are pushing a reference to the same object. Thus when making changes in the input field, you are seeing the updates in all array nodes - they reference the same item.

The quick fix is to push a copy of item, instead of item itself in $scope.add():

$scope.array.push(angular.copy(item));

The better way is to have item as an object, which you can instantiate:

var Item = function (){
    return {
        name: '',
        phone: '',
        email: ''
    };
};

then

$scope.array.push(new Item());

1 Comment

Thanks! And I really appreciate for your explanation of the reference! I really helped the issue and understanding the concept more!
1

Change your javascript to like this:

angular.module('myapp', [])
.controller('Ctrl', ['$scope', '$compile',function ($scope, $compile) {
  $scope.array = [];

  var item = {
    name: '',
    phone: '',
    email: '',
  };

  $scope.array.push(item);
  $scope.addItem = function () {
    item.name = $scope.name;
    item.phone = $scope.phone;
    item.email = $scope.email;
    $scope.array.push(item);
    $scope.name = "";
    $scope.phone = "";
    $scope.email = "";
  };
}]);

You will have to store each of the name, email and phone is separate models.

After that, when you add the item in your array make sure you reset them.

Also change the name of the model in the html.

Check here.

3 Comments

Nothing changes
@Supergentle Did you change the models in the html?
Thanks I solved problem by another's solution. However, I see it works in your codepen. Great thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.