How to run the loop data one by one after you splice the index

I have an array that I need to display one by one, and when the button is click it will go to the next index.

I am using splice so that after I shown the first index I will remove the first index by using splice.

function displayQuestionForScenario() {
    $.ajax({
        url: url,
        type: "GET",
        dataType: "json",
        success: function(data) {

            question_data = data.questions;

            console.log(question_data);

            for (var i = 0; i < question_data.length; i++) {

                question_length = question_data.length;

                $('#display_question_scenario').text("1." + " " + question_data[i].question);

            
                $('.btn_submit').show();

                question_data.splice(i, 1);
                console.log(question_data);
                break;
            }

        },
        error: function(jqXHR, textStatus, errorThrown) {
            alert('Error adding / update data');
        }
    });
}

Here is the look of the json that i am looping.

[0] => Array (
    [question] => What major problem are Texans having?
    [question_id] => 1
    [choices] => Array (
        [0] => Array (
            [choices] => gas shortage
            [choice_id] => 1
            )
        [1] => Array (
            [choices] => panic buying
            [choice_id] => 2
            )
        [2] => Array (
            [choices] => Hurricane Harvey
            [choice_id] => 3
            )
        [3] => Array (
            [choices] => help from oil companies
            [choice_id] => 4
            )
        )
    )
[1] => Array (
    [question] => What did civic leaders suggest?
    [question_id] => 2
    [choices] => Array (
        [0] => Array (
            [choices] => for people to purchase normally
            [choice_id] => 5
            )
        [1] => Array (
            [choices] => for markets to increase their prices
            [choice_id] => 6
            )
        [2] => Array (
            [choices] => for people to stock up while they can
            [choice_id] => 7
            )
        [3] => Array (
            [choices] => for drivers to rush to refill their tanks
            [choice_id] => 8
            )
        )
    )
[2] => Array (
    [question] => What is the author’s general intention in writing this article?
    [question_id] => 3
    [choices] => Array (
        [0] => Array (
            [choices] => to make everyone panic over gas shortages
            [choice_id] => 9
            )
        [1] => Array (
            [choices] => to publish how Texans reacted to fuel scarcity
            [choice_id] => 10
            )
        [2] => Array (
            [choices] => to announce the effects of Hurricane Harvey in Texas
            [choice_id] => 11
            )
        [3] => Array (
            [choices] => to inform the public of the closing of several oil refineries
            [choice_id] => 12
            )
        )
    )


the length of my array is 3, so i first need to display the index 0 then when the user click the button, i will splice my array then go to the next index.

if my question_data.length is still not zero it means that there is still data in my variablequestion_data, my goal is when I click the button it will continue the loop, but I don’t know how to do it after I splice it. can anyone help me to figure this out. any help would be really appreciated.

Answer

TL;DR Answer

Don’t use a loop! Instead, keep an index variable to track the current question, update it when the button is clicked and use it to select the next question.

Longer Explanation

You cannot use a loop for this, because the loop runs immediately from start to end. What you want instead (if I’m not mistaken) is to display each question after the user submitted the preceeding question.

To do this, you can make use of closures (simply google “javascript closures” for vast amounts of explanations). Let’s define a function that takes a counter variable, a list of questions and an element to render the questions into, and returns us another function that, when called, increments the counter and displays the question.

function getQuestionRenderer(initialCount, questions, $display) {
  var currentCount = initialCount;                     // this is the counter
  return function () {                                 // <-- 
    var q = questions[currentCount];                   // get question text
    if (q !== undefined) {                             // if q isn't undefined
      currentCount += 1;                               // increment counter
      $display.text(currentCount + ". " + q.question); // render question text
    }
  }
}

What’s that good for? It allows us to get an encapsulated “renderer” function, that automatically cycles through a list of questions. Assuming your data.questions array looks at least something like this:

[{ question: 'A?' }, { question: 'B?' }, { question: 'C?' }]

getQuestionRenderer can be used like this (manually):

var questions = [ /* ... elided, see above ... */ ];
var $displayEl = $('#display_question_scenario');

function getQuestionRenderer(initialCount, questions, $display) {
  // ... elided, see above ...
}

// 1. get the renderer function
var renderNext = getQuestionRenderer(0, questions, $displayEl);

// 2. render the first question
renderNext();

// 3. render the next questions
renderNext();
renderNext();

However, instead of calling renderNext 3 times, we can use it inside of a event handler function that’s executed when the button is clicked.

Start by defining the event handler:

function handleClick(callRenderNext) {
  return function (event) {
    event.preventDefault();  // prevent potential form submission (not sure if needed)
    callRenderNext();        // call renderNext again
  }
}

Attach it to the button:

var questions = [ /* ... elided, see above ... */ ];
var $displayEl = $('#display_question_scenario'),
    $btnEl = $('.btn_submit');

function getQuestionRenderer(initialCount, questions, $display) {
  // ... elided, see above ...
}

function handleClick(callRenderNext) {
  // ... elided, see above ...
}

// 1. get the renderer function
var renderNext = getQuestionRenderer(0, questions, $displayEl);

// 2. add click handler to buttons
$btnEl.on('click', handleClick(renderNext));

// 3. render the first question
renderNext();

All that’s left to do, is pack this into the success callback of your AJAX request and you’re good to go:

function displayQuestionForScenario() {
  $.ajax({
    url: url,
    type: "GET",
    dataType: "json",
    success: function(data) {
      var $displayEl = $('#display_question_scenario'),
          $btnEl = $('.btn_submit');

      var renderNext = getQuestionRenderer(
        0, 
        data.questions,
        $displayEl
      );

      $btnEl.on('click', handleClick(renderNext));
      renderNext();

      // Don't forget to show the button!
      $btnEl.show();
    },
    error: function(jqXHR, textStatus, errorThrown) {
      alert('Error adding / update data');
    }
  });
}

function getQuestionRenderer(initialCount, questions, $display) {
  // ... elided, see above ...
}

function handleClick(callRenderNext) {
  // ... elided, see above ...
}

Working (sync) example

var questions = [
  { question: 'A?' }, 
  { question: 'B?' }, 
  { question: 'C?' }
];


var $displayEl = $('#display_question_scenario'),
    $btnEl = $('.btn_submit');


function getQuestionRenderer(initialCount, questions, $display) {
  var currentCount = initialCount;            
  return function () {                         
    var q = questions[currentCount];          
    if (q !== undefined) {                       
      currentCount += 1;             
      $display.text(currentCount + ". " + q.question);         
    }
  }
}

function handleClick(callRenderNext) {
  return function (event) {
    event.preventDefault();
    event.stopPropagation();

    callRenderNext();
  }
}

var renderNext = getQuestionRenderer(0, questions, $displayEl);

$btnEl.on('click', handleClick(renderNext));
renderNext();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="display_question_scenario"></div>
<button class="btn_submit">Next</button>

Side Note

It seems you have several places in your JS that could be improved. I’ll list them one by one below:

  1. An implicit global variable question_data is created.
  2. Another implicit global variable question_length is created.
  3. $('#display_question_scenario').text( ... ) overrides previously written content.
  4. $('.btn_submit').show() is called repeatately.