Dee J. Dee J. - 4 months ago 11
AngularJS Question

How to add values in an array inside an array in AngularJS

I apologize if my title sounds so confusing, as I don't know how to exactly word it. Basically, this is what I'm trying to do.

For example, I have the following array:

var sourceArray = [
{ question: "Question 1", inputType: "radio", answer: "Answer 1", id: "1" },
{ question: "Question 1", inputType: "radio", answer: "Answer 2", id: "2" },
{ question: "Question 1", inputType: "radio", answer: "Answer 3", id: "3" },
{ question: "Question 2", inputType: "radio", answer: "Answer 1", id: "4" },
{ question: "Question 2", inputType: "radio", answer: "Answer 2", id: "5" },
{ question: "Question 2", inputType: "radio", answer: "Answer 3", id: "6" }
]


I want to restructure this so that it'll look like this:

var newArray = [
{
question: "Question 1", inputType: "radio",
choices: [{answer: "Answer 1", id: "1"},
{answer: "Answer 2", id: "2"},
{answer: "Answer 3", id: "3"}
]},
{
question: "Question 2", inputType: "radio",
choices: [{answer: "Answer 1", id: "4"},
{answer: "Answer 2", id: "5"},
{answer: "Answer 3", id: "6"}
]}
]


Answers are grouped by question, so if the next question in the
sourceArray
is the same with the current, it will push the answers into the
choices
array.

Is this possible in AngularJS using angular.forEach?

Any help will be appreciated.

Thank you as always for your responses.

Answer

Here you go. See the working example below:

// Add a hepler method in the Array to find the value
Array.prototype.find = function(key, value) {
  var index = -1;
  angular.forEach(this, function(item, i) {
    if (item[key] === value) {
      index = i;
    }
  });

  return this[index];
};

var app = angular.module("sa", []);

app.controller("FooController", function($scope) {

  $scope.sourceArray = [{
    question: "Question 1",
    inputType: "radio",
    answer: "Answer 1",
    id: "1"
  }, {
    question: "Question 1",
    inputType: "radio",
    answer: "Answer 2",
    id: "2"
  }, {
    question: "Question 1",
    inputType: "radio",
    answer: "Answer 3",
    id: "3"
  }, {
    question: "Question 2",
    inputType: "radio",
    answer: "Answer 1",
    id: "4"
  }, {
    question: "Question 2",
    inputType: "radio",
    answer: "Answer 2",
    id: "5"
  }, {
    question: "Question 2",
    inputType: "radio",
    answer: "Answer 3",
    id: "6"
  }];

  $scope.newArray = [];

  $scope.convert = function() {
    // Iterate array
    angular.forEach($scope.sourceArray, function(item) {
      // Check if the question alrady exists
      if (!$scope.newArray.find('question', item.question)) {
        // If not, push the question to the array with empty choices
        $scope.newArray.push({
          question: item.question,
          inputType: item.inputType,
          choices: []
        });
      }

      var newArrayItem = $scope.newArray.find('question', item.question);
      
      // Push the choices
      newArrayItem.choices.push({
        answer: item.answer,
        id: item.id
      });
    });
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">


<div ng-app="sa" ng-controller="FooController">
  Before:
  <br>{{sourceArray | json}}
  <br>
  <a href="" ng-click="convert()">convert</a>
  <br>After:
  <br>{{newArray | json}}
</div>