Eric Mitjans
Eric Mitjans

Reputation: 2179

Pushing input values from ng-repeat into array with AngularJS

I have a ng-repeat displaying a list of products with an input each. I want to be able to push the value of each input together with a parameter from every item into a new array to create an order.

So far I managed to do it individually, but not all together.

Here's my HTML:

<div ng-repeat="pa in products">
  <div>
    <h2>{{pa.nom}}</h2>
    <input type="number" ng-model="basket" min="0" max="20" step="1" ng-init="basket=0">
  </div>
</div>
<a ng-click="insert(pa.nom,basket)">Add items</a>

And the function:

$scope.singleorder = [];

$scope.insert = function(nom, basket){
  $scope.singleorder.push({
    'product': nom,
    'number': basket
  });
  console.log($scope.singleorder);
}

I assume the issue has to do with keeping track of the different models of the inputs on each repeat, but I don't know how to deal with it.

I've also tried adding each item individually using ng-change on the input, but it will push an object on every change, duplicating the item on every change, so it won't work.

Any tips?

Upvotes: 3

Views: 4984

Answers (3)

Mistalis
Mistalis

Reputation: 18289

The trick would be to have an input for each repeated element in ng-repeat.

<div ng-repeat="pa in products">
    {{pa.nom}}
    <input type="number" ng-model="pa.basket">
</div>
<a ng-click="insert()">Add items</a>

insert() will loop over products and insert in singleOrder when basket has been set:

$scope.insert = function() {
    for (var i = 0; i < $scope.products.length; i++) {
        if ($scope.products[i].basket) { // if input has been set
            $scope.singleorder.push({
              'product': $scope.products[i].nom,
              'number': $scope.products[i].basket
            });
        }
    }
}

JSFiddle demo

Upvotes: 6

Apostolidis
Apostolidis

Reputation: 114

There are 2 ways to do this.

  • The first way is to mutate the products collection by adding the quantity property.
  • The other way is to keep a separated collection that keeps track of the quantity.

HTML (way 1):

<div ng-repeat="pa in products">
  <div>
    <h2>{{pa.nom}}</h2>
    <input type="number" ng-model="pa.quantity" min="0" max="20" step="1">
  </div>
  <a ng-click="insert(pa)">Add items</a>  
</div>

Javascript (way 1):

$scope.singleorder = [];

$scope.insert = function(pa){
  $scope.singleorder.push({
    'product': pa.nom,
    'number': pa.quantity || 0
  });
  console.log($scope.singleorder);
}

HTML (way 2):

<div ng-repeat="pa in products">
  <div>
    <h2>{{pa.nom}}</h2>
    <input type="number" ng-model="productsQunatity[pa.nom]" min="0" max="20" step="1">
  </div>
  <a ng-click="insert(pa.nom,productsQunatity[pa.nom])">Add items</a>  
</div>

Javascript (way 2):

$scope.singleorder = [];
$scope.productsQunatity = {};

$scope.insert = function(nom){
  $scope.singleorder.push({
    'product': nom,
    'number': $scope.productsQunatity[nom] || 0
  });
  console.log($scope.singleorder);
}

Keep in mind that you should probably avoid the duplications. So, i propose to check if you already have already a product with the specific id.

$scope.insert = function(pa) {
  var product = $scope.singleorder.find(function(product) {
    return product.nom === pa.nom;
  });

  if (product) {
    product.number += pa.quantity || 0;
  } else {
    $scope.singleorder.push({
      'product': pa.nom,
      'number': pa.quantity || 0
    });
  }

}

Upvotes: 0

Rakesh Chand
Rakesh Chand

Reputation: 3113

Intialize a array and push a empty dictionary every time you click add more

$scope.products = [];
$scope.addNew = addNew;
function addNew(){
  $scope.products.push({});
}

And you html would look like this

<div ng-repeat="pa in products">
    <input type="number" ng-model="pa.basket">
</div>

You can put validation over add button, that do not add more until you entered value in previous.

It will automatically form a json in the format of

[{
   basket : 'value'
}]

Upvotes: 0

Related Questions