Leveraging angular.forEach for JSON Iteration

In my app and controller, I am working on creating a "flow chart style" question and answer system. To keep track of the current question and answer, I am using variables like $scope.ActiveQuestion and an array named $scope.ActiveAnswers.

I am struggling to grasp the concept of AngularJS foreach method as I am more familiar with traditional for loops in JavaScript. Despite searching for explanations comparing foreach to for loops, I have come up empty-handed. However, here is what I am attempting to achieve using the foreach method.

For each answerIDs in the current set of

$scope.questions[$scope.ActiveQuestions].answerIDs
, I aim to access the corresponding array in Answers containing that particular idAnswer and then add it to a newly created empty array called $scope.ActiveAnswers. This process will enable me to use ng-repeat in a template to display the necessary answers for that specific question.

Below, you can examine the JSON data alongside my current Controller code:

app.controller('QuestionsCtrl', function($scope, $http) {

    // Fetch Questions data
    $http.get("includes/getQuestions.php")
    .success(function(response) {
        $scope.Questions = response;
        $scope.ValidAnswers = $scope.Questions[$scope.ActiveQuestion].answerIDs.split(",");
    });
    // Fetch Answers data
    $http.get("includes/getAnswers.php")
        .success(function(response) {
            $scope.Answers = response;
        });

    // Assign First Question
    if ($scope.ActiveQuestion == null) {
        $scope.ActiveQuestion = 1;
    };
    $scope.ActiveAnswers = [];
    angular.forEach($scope.Answers, function(idAnswers) {
        angular.forEach($scope.ValidAnswers, function(value) {
            if(value==idAnswers) {
                this.push(Answers)
            };
        });
    },$scope.ActiveAnswers);

});

Questions:

[
    [], {
        "idQuestion": "1",
        "answerIDs": "1",
        "text": "Don't know what to watch?"
    }, {
        "idQuestion": "2",
        "answerIDs": "2,3,4",
        "text": "Okay! First question: How new to anime are you?"
    }, {
        "idQuestion": "3",
        "answerIDs": "5,6,7,8,9,10",
        "text": "So you're new! Awesome, I've got tons of anime for you. But let's get more specific. What type of anime interests you?"
    }, {
        "idQuestion": "4",
        "answerIDs": "11,12,13",
        "text": "Cool, cool. What setting would you like?"
    }
]

I have also compiled an array of answers:

[
    [], {
        "idAnswer": "1",
        "nextQuestion": "2",
        "text": "Click here to get started",
        "animeID": null,
        "checkType": "0"
    }, {
        "idAnswer": "2",
        "nextQuestion": "3",
        "text": "...I've seen some GIFs",
        "animeID": null,
        "checkType": "0"
    }, {
        "idAnswer": "5",
        "nextQuestion": "4",
        "text": "Fantasy Action Adventure",
        "animeID": null,
        "checkType": "0"
    }, {
        "idAnswer": "11",
        "nextQuestion": null,
        "text": "Steampunk (magic, guns, early 1900s)",
        "animeID": "1",
        "checkType": "1"
    }
]

Although no errors are displayed, the ActiveAnswers array remains unfilled. Any assistance on this matter would be highly appreciated.

UPDATE

Furthermore, it is worth mentioning that I initially store my data in a MySQL database and retrieve it using PHP by encoding it into JSON format.

Answer №1

To effectively manage your requests, you can utilize the promise feature along with the $q.defer() promise manager.

It is important to note that $http inherently returns a promise.

The $q.defer() function provides 2 essential methods:

  • resolve(value) : used to resolve the associated promise by providing the final value

  • reject(reason) : resolves a promise error

In the Controller:

(function(){

function Controller($scope, Service, $q) {


  var defer = $q.defer();

  //creating promises
  var promise1 = Service.get('includes/getQuestions.php"');

  var promise2 = Service.get('includes/getAnswers.php');

  //Creating promise using $q
  var promiseAnswer = defer.promise;

  if ($scope.ActiveQuestion == null) {
      $scope.ActiveQuestion = 1;
  };

  //Retrieving data from promise1 & promise2
  $q.all([promise1, promise2]).then(function(response){
    //Getting question data
    $scope.Questions = response[0].data;
    //Getting answer data
    $scope.Answers = response[1].data;
    $scope.ValidAnswers = $scope.Questions[$scope.ActiveQuestion].answerIDs.split(",");
    $scope.ActiveAnswers = [];

    $scope.Answers.forEach(function(elm){
      $scope.ValidAnswers.forEach(function(value){
        //Accessing elm.idAnswer instead of just elm
        if (value === elm.idAnswer){
          $scope.ActiveAnswers.push(value);
        }
      });
    });

    //Resolving our data
    defer.resolve($scope.ActiveAnswers);

  });

  //Once all data is processed, retrieve the data
  promiseAnswer.then(function(data){
    console.log(data);
  });

}

angular
.module('app', [])
.controller('ctrl', Controller);

})();

Additionally, it is recommended to use a Service for processing requests:

Service

(function(){

  function Service($http){

    function get(url){
      //Returns a promise with the specified URL
      return $http.get(url);
    }

    var factory = {
      get: get
    };

    return factory;

  }

  angular
    .module('app')
    .factory('Service', Service);

})();

When dealing with multiple asynchronous requests, utilizing promise and $q.defer() is considered a best practice.

Answer №2

I suggest creating a structure named "Solution" in your code, storing it in an array, and iterating through it like this:

[
 ["Question"],
   ["Solution"]
   {
    "idSolution": "1",
    "nextStep": "2",
    "description": "Click here to begin",
    "animeID": null,
    "validationType": "0"
   },
]

This approach will ensure the loop runs smoothly without any issues.

Answer №3

Thanks to the collaborative effort of everyone here, I successfully resolved the issues with my code without making any changes to the database. I managed to fix the problems with the foreach loops and although there are still some issues remaining, the main challenges in this task have been addressed. Below is the updated version of my code snippet.

app.controller('QuestionsCtrl', function($scope, $http, $window) {

// Setting the initial active question
if ($scope.ActiveQuestion == null) {
    $scope.ActiveQuestion = 1;
};
// Retrieving questions data
$http.get("includes/getQuestions.php").success(function(responseQuestions) {
    $scope.Questions = responseQuestions;
    $scope.ValidAnswers = $scope.Questions[$scope.ActiveQuestion].answerIDs.split(",");

    // Retrieving answers data
    $http.get("includes/getAnswers.php").success(function(responseAnswers) {
        $scope.Answers = responseAnswers;
        $scope.getActiveAnswers();
    });
});

$scope.getActiveAnswers = function() {
    $scope.ValidAnswers = $scope.Questions[$scope.ActiveQuestion].answerIDs.split(",");
    $scope.ActiveAnswers = [];
    angular.forEach($scope.ValidAnswers, function(answerid) {
        angular.forEach($scope.Answers, function(answer) {
            if (answer.idAnswer == answerid) {
                $scope.ActiveAnswers.push(answer);
              };
          });

      }, $scope.ActiveAnswers);
}

$scope.answerclick = function(nextQuestion) {
    $scope.ActiveQuestion = nextQuestion;
    $scope.getActiveAnswers();
};

});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Execute command problem

Explaining this code may be a bit tricky, but I'll do my best. Below is the code snippet for executing a slash command. client.on('interactionCreate', async interaction => { if (!interaction.isCommand()) return; const command = c ...

Implementing image loading within an accordion component using React and Material UI

I'm working with a React Accordion component using Material UI. Each time I open a tab in the Accordion, I want to load different images from another div that is located outside of the Accordion. Here is the current code snippet: export default funct ...

What steps do I need to take to transform this click event function into one that is triggered automatically upon the div loading?

In order to automatically load content into a div using innerHTML, the PHP file must be retrieved and the div updated with its content. Within this div is another one labeled "tweet" which displays actual tweets based on a specific hashtag provided through ...

Ways to randomize an array without any repeating elements with the help of jQuery?

let numbers = [5, 12, 18, 23, 30]; What is the most efficient way to randomize the order of these numbers in a new array without any duplicates? Example: newArr = [18, 30, 5, 12, 23]; ...

If I don't utilize a promise for my trigger.io AJAX request, the value of AngularJS $rootScope will not

Something strange is happening. The variable $rootScope seems to be assigned correctly within a function, but then unexpectedly loses its value. It only retains the value if I incorporate a promise. How peculiar! During a trigger.io (Forge) AJAX request, ...

Issue with clientHeight not functioning properly with line breaks in Angular 2 application after ngAfterViewInit

I have successfully created a Gridify page in my Angular 2 application using the Gridify library. To initialize it, I've utilized a custom ngAfterViewChecked method: ngAfterViewChecked() { var selector = document.querySelector('.read-grid& ...

How to manage form submissions in Vue.js using inputs within child components

I'm working on a parent component that acts as a form. This form consists of multiple child components, each containing input fields. <template> <div class="form"> <generalData v-model="input" /> <textAreas v- ...

Tips for handling Promise.all and waiting for all promises to resolve in an async function in Express JS

I'm relatively new to JavaScript and especially asynchronous programming. My current project involves creating an Express+React application that shows a GitHub user's information, including a few repositories with the latest 5 commits for each. ...

Saving form data with a tinymce textarea, radio button, and checkbox to the database

My form contains multiple textarea fields, radio buttons, checkboxes, and a select input. Initially, I was able to submit the form using PHP without any issues. However, when I integrated TinyMCE with one of the textareas, I had to introduce JavaScript to ...

This function is designed to only work under specific conditions

Looking for assistance with a function that takes an item ID as input and changes its border when pressed. The goal is to increase the border width by 2px when there is no border, and remove the border completely when pressed again. Currently, only the f ...

Is it possible to include array elements in a dropdown menu using React?

Imagine you have an array called const places = [" a1", "a2", "a3"]; and <FormControl variant="outlined" className={classes.formControl}> <InputLabel id="dropdown_label">Testing</InputL ...

An issue occurred while attempting to serialize or deserialize data with the JSON JavaScriptSerializer. The length of the string exceeds the allowable limit

""""""""""""""""""Issue encountered during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the maximum value set on the maxJsonLength property.","StackTrace":" at System.Web.Script.Serializatio ...

Struggling to integrate a JavaScript sdk with an Angular2 application due to missing dependencies

I've been struggling to incorporate the Magic: The Gathering SDK library into my Angular2 application. I've tried various methods, but nothing seems to work seamlessly. When I attempt to import the library using TypeScript like this: import { } ...

Creating a map with multiple markers by utilizing JSON, PHP, and Google Maps API Version 2

I am currently working with Google Maps API V2 (I know, it's outdated but I have to stick with V2 because I am modifying existing code). All the markers on the map are pointing to the correct locations, but there's one infuriating issue that is d ...

Fade-in a new, revised text after fading-out the original text in ReactJS

I have a bunch of p elements that I'd like to cycle through, fading in one at a time and then replacing it with the next. Here is the jQuery example on CodePen: https://codepen.io/motion333/pen/EBBGVM Now, I'm attempting to achieve the same effe ...

Using the "this" keyword is required for an Angular Service-created function

Although this question leans more towards JavaScript than Angular, I encountered an issue while creating a service. The function call looked like this: // controller injects activityApi , then service function call is made var activities = activityApi.get ...

Utilizing Regular Expressions in AngularJS to validate name, a 10-digit mobile number, and a 12-digit number through the ng-blur event and match

I am struggling to validate the three inputs mentioned above and having trouble using the right functions. Can someone please assist me with this? Here is the HTML code for the 3 inputs: <input id="name" ng-model="user.name" ng-blur="checkIfNameIsVali ...

use php code to dynamically populate a select dropdown element with jquery

Here's my query: Array ( [0] => Array ( [idCustomer] => 2553 [session] => [noMobil] => 666 [keterangan] => Sistem [tahun] => 2012 [merk] => Sist ...

How do I ensure that a nested <button> in AngularJS does not submit the form it is contained in?

My current project involves a form in AngularJS used for inputting data into a movie database. The form includes a dropdown menu allowing users to select actors to add to the movie record they are creating. However, when the user clicks the button next t ...

Parse a string and generate an array using regular expressions in JavaScript/Node.js

I'm currently working on coding in JavaScript to extract an array of elements after splitting using a regular expression. var data = "ABCXYZ88"; var regexp = "([A-Z]{3})([A-Z]{3}d{2})"; console.log(data.split(regexp)); The current output is [ &a ...