0

I want to have an Object with a two dimensional array in it. it will hold questions with associated choices and the correct answer. The first time thru it works correctly but the second time with i= 1 k= 0 I get an exception. Here is the relevant code with the exception thrown after the first entry in the object:

var testquestions = [{
        question:[],
        choices:[[]],
        answer:[],
       }
      ];
      var i = 0;

 $( "#opener" ).click(function() {
          $( "#dialog" ).dialog( "open" );
          $( "#dialog" ).dialog({
            minWidth: 700,
            minHeight: 650,
            buttons: [
                 {
                   text: "Add Question",
                   click: function() {
                       i = testquestions[0].question.length;
                       testquestions[0].question[i] = $( "#question" ).val();
                       for(var k = 0; k < 4; k++){
                           if ($("#" + k).val() != "")  {
                             alert("i and k values are " + i + "nd " + k);
                             testquestions[0].choices[i][k] = $( "#" + k ).val();
                           }
                        }  // for k
                      testquestions[0].answer[i] = $("#correctAnswer").val();
                      $("#test")[0].reset();
                      alert(testquestions[0].question[i]);
                    }
                 }

exception

TypeError: testquestions[0].choices[i] is undefined

testquestions[0].choices[i][k] = $( "#" + k ).val();

Can someone tell me if I am declaring and invoking the 2-d array correctly? The exception gets thrown when i = 1. Thanks Update: Answer below did solve my problem.

1 Answer 1

2

testquestions[0].choices[i] is not defined (because of choices:[[]]) and never assigned, so you can't access it with [k]. Add a

testquestions[0].choices[i] = [];

right below the

testquestions[0].question[i] = $( "#question" ).val();

to fix that.

Notes:

  • var foo = { choices:[[]] } is equivalent to

    var foo = {};
    foo.choices = [];
    foo.choices[0] = [];
    

    It initializes the choices field to be an array with one element: an empty array. So, .choices[0] exists, but choices[1] does not, which causes the error on choices[1][k].

  • Tou might want to use console.log() (press F12 to see it) instead of alert(), as that gets annoying inside loops. ;-)

  • It's best not to use #1. See the note on this page: have an id always start with a letter.

  • Since a question always has some (4) options, perhaps you could use this structure: { question: "?", choices: ["A","B","C"], answer: "C" }

    var testquestions = [];
    
    function addQuestion( q, c, a ) {
        testquestions.push( { question: q, choices: c, answer: a } );
    }
    

    and your handler:

     click: function() {
                addQuestion( 
                    $( "#question" ).val(),
                    $( 'input.choice' ).map( function(i,e){ return $(e).val();}).get(),
                    $("#correctAnswer").val()
                );
    
                $("#test")[0].reset();
              }
    

    you would need to change the <input id='1'> ... <input id='4'> to <input class='choice'>.

update

var testquestions = [{
        question:[],
        choices:[],
        answer:[],
       }
      ];
      var i = 0;

$( "#opener" ).click(function() {
   i = testquestions[0].question.length;
   testquestions[0].question[i] = $( "#question" ).val();
   testquestions[0].choices[i] = [];
   for(var k = 0; k < 4; k++){
     if ($("#c" + k).val() != "")  {
       testquestions[0].choices[i][k] = $( "#c" + k ).val();
     }
   }  // for k
   testquestions[0].answer[i] = $("#correctAnswer").val();
   console.log("Added question", testquestions[0] );
   $("#test")[0].reset();                      
 }
);
fieldset { display: inline-block; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='dialog'>
  <form id='test'>
    Q <input id='question'/><br/>
    A <input id='correctAnswer'/><br/>
    C <fieldset label='foo' title='bar'>
    <input id='c0' class='choice'/><br/>
    <input id='c1' class='choice'/><br/>
    <input id='c2' class='choice'/><br/>
    <input id='c3' class='choice'/><br/>
    </fieldset>
    <button id='opener'>add question</button>
  </form>
</div>

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. Works now. Did I not declare the 2-d array correctly? I declared choices[[]] I thought would create an empty choices 2-d array that could be referenced with nothing further. if you could expand much appreciated
I added a note on that. It partially works. It does initialize choices[0] with the array [], but not choices[1]. You'd need to write choices: [ [], [] ], but you won't know how many you need in advance, so it's best to allocate the array in the click handler and simply write choices: []. I also suggested a slightly different approach. (If that jQuery map is over your head, all it does is create an array populated with the values of #1 etc; i wanted to keep the code short).
Damn. You did more in 5 mins then I have in two days:) Thanks for elucidating the answer as I will be coming back to it as a reference.
JS is a struggle at first, but it gets easier ;)
Still have one problem. I put in line console.log(testquestions[0].question[i] + testquestions[0].choices[i][k] + testquestions[0].answer[i]); after testquestions[0].answer[i] = $("#correctAnswer").val(); line and all the choices items show as undefined in console. Any thoughts.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.