简体   繁体   中英

How to store value of all the checked box to an array and pass it to PHP function using AJAX call?

I am making an Exam-Test Module. In which there will be more than one questions. Each questions has multiple choice answers. I am showing one question at a time. There will be a button called 'Next' till the last question appears. If there are no more questions, the button will say Submit Test . When user clicks on Submit Test button, all answers of all the questions will be passed to PHP function in the backend to check how many are correct and wrong? I tried doing the following thing but I am getting the array with only one answer and that of first question. How can I achieve this ? I want to store the answers of all the questions in one array and then pass that array to PHP function through AJAX .post call or jQuery call ?

index.php

<div class="modal fade test-modal" id="Test">
    <div class="modal-dialog">
        <div class="modal-content">
            <? foreach ($questions as $i=>$question) { ?>
            <div class='question'>
                <div class="modal-header">
                    <div class="row">
                        <h4>QUIZ</h4>
                    </div>
                </div>
                <div class="modal-body">
                    <div class="row">
                        <div class="quest">
                            <ul class="list-unstyled">
                                <? foreach ($question->getAnsChoice as $answer) { ?>
                                    <li>
                                        <div class="checkbox">
                                                <input class="cb" type="checkbox" name="answer[]" value="<?=$answer->title?>">
                                                <?=$answer->title?> 
                                        </div>
                                    </li>
                                <? } ?> 
                            </ul>
                            <br>
                            <br>
                            <p class='error'>Please select an answer</p>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <p class='quest_num'><?=$question->number?> of <?=count($questions)?></p>
                    <?  if( count($questions) === 1 ) { ?>
                        <a id="submit_quiz" class="btn button btn-lg quiz-btn">Submit Test</a>
                    <? } else if ( count($questions) === $i +1 ) { ?>
                        <a id="submit_quiz" class="btn button btn-lg quiz-btn">Submit Test</a>
                    <? }  else { ?>
                        <a class=" btn button btn-lg quiz-btn">Next Question</a>
                    <? } ?>
                </div>
            </div>
            <? } ?>
        </div>
    </div>
</div>

javascript

<script type="text/javascript">
    $(document).on('ready', function(){
        $('.quiz-btn').click(function(e){
            e.preventDefault()
            var checkbox = $(this).parents('.question').children('.modal-body').children('.row').children('.quest').children('ul').children('li').children('.checkbox').children('.icheckbox_square');
            var btn = $(this).parents('.question').children('.modal-footer').children('.quiz-btn')
            var next = false
            var submit = false
            var answers = [];
            $(checkbox).each(function(){
                if ( $(this).hasClass('checked') && $(btn).html() == 'Next Question' ) {
                    answers.push($('.cb:checked').val());
                    next = true
                } 
                else if ($(this).hasClass('checked') && $(btn).html() == 'Submit Test') {
                    submit = true
                }
            });

            if ( next ) {
                e.preventDefault();
                $(this).parents('.question').slideUp(500);
                $(this).parents('.question').next('.question').delay(500).slideDown(500);
            } else if ( submit ) {
                e.preventDefault();
                $.post('/student/submit_quiz',{asnwers: answers}, function(data){

                });
            } else {
                console.log(next)
                $('.quest .error').fadeIn();
            }
        });
    }
</script>

There are a couple of issues with this code that I've noticed:

$(checkbox).each(function(){
    if ( $(this).hasClass('checked') && $(btn).html() == 'Next Question' ) {
        answers.push($('.cb:checked').val()); // LOGIC ERROR
        next = true
    } 
    else if ($(this).hasClass('checked') && $(btn).html() == 'Submit Test') {
        submit = true
    }
});

The line of code that I've marked with a comment is querying the entire document for all checkboxes matching '.cb:checked' with $('.cb:checked') . Then, JQuery's .val() function gets the value of just the first element from that collection.

Here is the relevant JQuery API documentation :

Description: Get the current value of the first element in the set of matched elements.

So the JavaScript iterates through every checkbox, then repeatedly adds just the first checkbox in the document's value to the array.

To fix this, get the value from the current this object:

if ( $(this).hasClass('checked') && $(btn).html() == 'Next Question' ) {
    answers.push($(this).val()); // modified line
    next = true
} 

The second is that the variable answers exists separately for each button. You have one button for each section and a new, separate function call for each button. You would need to hoist the answers variable outside of the event function:

$(document).on('ready', function(){
    var answers = [];
    $('.quiz-btn').click(function(e){
        // Bla bla bla
        answers.push(the_correct_value);
        // Bla bla bla
    });
}

If you don't want the answers variable to be available to everything in the document.ready event listener, you can use a pattern called an Immediately Invoked Function Expression:

$(document).on('ready', function(){
    (function(){ // Notice how this line starts with an open bracket
        var answers = [];
        $('.quiz-btn').click(function(e){
            // Bla bla bla
            answers.push(the_correct_value);
            // Bla bla bla
        });
    })(); // This line closes the open bracket above, 
          // then immediately runs the result with no arguments

    // the `answers` variable is unavailable in this scope
}

The JavaScript that you included was also missing a closing bracket at the very end of the script.


All that said, the solution I would use personally would be to wrap the whole thing in a form, use a submit button, listen for the form's submit event and just create a JavaScript FormData to send the answers:

<div class="modal fade test-modal" id="Test">
    <div class="modal-dialog">
        <div class="modal-content">
            <form action="/student/submit-quiz" method="POST"><!-- Form tag -->
                <?php foreach($questions as $i => $question): ?>
                <div class="question">
                    <div class="modal-header">
                        <div class="row">
                            <h4>QUIZ</h4>
                        </div>
                    </div>
                </div>
                <div class="modal-body">
                    <div class="row">
                        <div class="quest">
                            <ul class="list-unstyled">
                                <?php foreach ($question->getAnsChoice as $answer): ?>
                                <li>
                                    <div class="checkbox">
                                        <input class="cb" type="checkbox" name="answer[]" value="<?= $answer->title ?>" />
                                        <?= $answer->title ?>
                                    </div>
                                </li>
                                <?php endforeach;  ?>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <p class="quest_num"><?= $question->number ?> of <?= count($questions) ?></p>
                    <?php $last = $question->number === count($questions) - 1; ?>
                    <!-- 
                    Ternary operators, used in these attributes, are like if statements:
                    if the first thing is true, return the second,
                    otherwise return the third.
                    -->
                    <input type="<?= $last ? 'submit' : 'button' ?>" class="btn button btn-lg quiz-btn" value="<?= $last ? 'Submit Test' : 'Next Question' ?>" />
                </div>
                <?php endforeach; ?>
            </form>
            <script>
                /*
                 * Where the real magic happens.
                 */
                $('form[action="/student/submit-quiz"]').on('submit', function(e) {
                    e.preventDefault();
                    data = new FormData(this);
                    $.ajax({
                        url: this.action,
                        data: data,
                        contentType: false,
                        processData: false,
                        type: 'POST',
                        success: function(response) {
                            // do something useful with the response
                            console.log(response);
                        },
                    });
                });

                $('form[action="/student/submit-quiz"] input[type="button"]').on('click', function(e) {
                    $(this).parents('.question').slideUp(500);
                    $(this).parents('.question').next('.question').delay(500).slideDown(500);
                });
            </script>
        </div>
    </div>
</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM