Search code examples
javascriptphphandsontable

Handsontable giving unexpected number of columns


I have implemented handsontable for getting data from user. This is my script

<script type="text/javascript">
    $(document).ready(function() {
        $('#quiz_questions').handsontable({
            rowHeaders: true,
            colHeaders: ['Question', 'Option 1', 'Option 2', 'Option 3', 'Option 4', 'Answer', 'Marks'],
            columns: [
                {
                  type: 'text',
                  allowEmpty: false
                },
                {
                  type: 'text',
                  allowEmpty: false
                },
                {
                  type: 'text',
                  allowEmpty: false
                },
                {
                  type: 'text',
                  allowEmpty: true
                },
                {
                  type: 'text',
                  allowEmpty: true
                },
                {
                  type: 'dropdown',
                  source: ['Option 1', 'Option 2', 'Option 3', 'Option 4'],
                  allowEmpty: false
                },
                {
                  type: 'numeric',
                  allowEmpty: false
                }
            ],
            stretchH: 'all',
            minSpareRows: 0,
            minSpareColumns: 0,
            minRows : 25
        });

        var hotInstance = $("#quiz_questions").handsontable('getInstance');

        $('#btnSave').click(function(e){
            e.preventDefault();
            $('#btnSave').prop("disabled", true);
            //alert('btnclicked');

            var dynFrm = $('<form>', {
                'action': '{{ action('QuizQuestionController@storeBulk') }}',
                'method': 'POST'
            }).append($('<input>', {
                'type': 'hidden',
                'name': '_token',
                'value': '{{ csrf_token() }}'
            })).append($('<input>', {
                'type': 'hidden',
                'name': 'quiz_id',
                'value': '{{ $quiz->quiz_id }}'
            })).append($('<input>', {
                'type': 'hidden',
                'name': 'data',
                'value': JSON.stringify(hotInstance.getData())
            }));
            dynFrm.appendTo(document.body).submit();
        });

    });

</script>

The storeBulk() function of QuizQuestionController processes the data.

public function storeBulk()
    {
        // get the quiz model
        $quiz = Quiz::findOrFail(Input::get('quiz_id'));

        // get the data
        $data = Input::get('data');
        $jData = json_decode($data);

        //process the recevied data
        foreach($jData as $row) {
            $quizQuestion = new QuizQuestion();

            $quizQuestion->quiz_id = $quiz->quiz_id;
            $quizQuestion->question_no = $cnt;
            $quizQuestion->question_text = trim($row[0]) ? : null;
            $quizQuestion->options = $this->processOptions([
                                        trim($row[1]),
                                        trim($row[2]),
                                        trim($row[3]),
                                        trim($row[4])
                                        ]);
            $quizQuestion->answer = $this->processAnswer($row[5]);
            $quizQuestion->marks = trim($row[6]) ? : null;

            ...
    }

Now the problem is, for rows that are left empty in the handsontable while filling the data, I should get data for those rows as [null,null,null,null,null,null,null]. But this is not the case. For some rows I get [null,null,null,null,null] (only 5 values). Thus I get an ErrorException saying Undefined offset: 5.

I have noticed this happens for first 5 rows only. What could be the problem?


Solution

  • Pinpointed the problem.

    I have noticed this happens for first 5 rows only. What could be the problem?

    There's a startRows property of handsontable which defaults to 5. Hence the problem with the first 5 rows. I set the property explicitly to

    startRows: 0,
    

    And also modified the storeBulk() function to ignore errors.

    $quizQuestion->question_text = trim(@$row[0]) ? : null;
    $quizQuestion->options = $this->processOptions([
                                       trim(@$row[2]),
                                       trim(@$row[3]),
                                       trim(@$row[4]),
                                       trim(@$row[5])
                                    ]);
    $quizQuestion->answer = $this->processAnswer(@$row[6]);
    $quizQuestion->marks = trim(@$row[7]) ? : null;
    

    Now everything works correctly.