Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Devin Gray
Devin Gray
39,261 Points

Dynamically Add Table Rows Using JavaScript

I'm trying to create a checkbox that hides and shows rows of the table as I check the boxes, and have "check all" and "uncheck all" buttons. I've been reading as much as I could on the subject but I'm still stumped on how to go about it. I feel like this should be easier but I know even less JavaScript than I thought.

Help would be very much appreciated.

Here's my HTML:

 <p>
      <label>
          <input type="checkbox" name="CheckboxGroup1" value="checkbox" id="CheckboxGroup1_0">
          Row 1</label>
      <br>
      <label>
          <input type="checkbox" name="CheckboxGroup1_" value="checkbox" id="CheckboxGroup1_1">
          Row 2</label>
      <br>
      <label>
          <input type="checkbox" name="CheckboxGroup1_" value="checkbox" id="CheckboxGroup1_2">
          Row 3</label>
      <br>
      <label>
          <input type="checkbox" name="CheckboxGroup1_" value="checkbox" id="CheckboxGroup1_3">
          Row 4</label>
      <br>
      <label>
          <input type="checkbox" name="CheckboxGroup1_" value="checkbox" id="CheckboxGroup1_4">
          Row 5</label>
  </p>
  <input name="Check All" type="button" id="Check All" title="Check All" value="Check All">
  <input name="Uncheck All" type="button" id="Uncheck All" title="Uncheck All" value="Uncheck All">
  <table width="100%" border="1" summary="This table is dynamically generated using JavaScript.">
      <caption>
          JavaScript Dynamic Table
      </caption>
      <tbody>
          <tr>
              <th scope="col">&nbsp;</th>
              <th scope="col">Column 1</th>
              <th scope="col">Column 2</th>
              <th scope="col">Column 3</th>
          </tr>
          <tr id="row1">
              <td>Row 1</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
          </tr>
        <tr id="row2">
              <td>Row 2</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
          </tr>
        <tr id="row3">
              <td>Row 3</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
          </tr>
        <tr id="row4">
              <td>Row 4</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
          </tr>
        <tr id="row5">
              <td>Row 5</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
              <td>&nbsp;</td>
          </tr>
      </tbody>
  </table>
  <p><br>
  </p>

Hi Devin,

If you look just below the text box area you will see something that says Markdown Cheetsheet. Also, there is a post here titled: Posting Code to the Forum by Dave McFarland. If you don't understand that maybe this will make sense: How to display code at Treehouse.

Jeff

Devin Gray
Devin Gray
39,261 Points

hahaha I thought I knew how to post it but I forgot to leave blank lines before and after the tilde marks, I was wondering why my code was acting up smh.

Devin Gray
Devin Gray
39,261 Points

in my attempts to figure this problem out, here's what I've come up with on my own, but I have no idea still how to make anything work.

// JavaScript Document
var firstCheckbox = $('#CheckboxGroup1_1');
var secondCheckbox = $('#CheckboxGroup1_2');
var thirdCheckbox = $('#CheckboxGroup1_3');
var fourthCheckbox = $('#CheckboxGroup1_4');
var fifthCheckbox = $('#CheckboxGroup1_5');

var firstRow = $('#row1');
var secondRow = $('#row2');
var thirdRow = $('#row3');
var fourthRow = $('#row4');
var fifthRow = $('#row5');

var toggle = function(checkbox, tablerow) {
  $(checkbox).click(function () {
    tablerow.toggle;
  })
};

toggle(firstCheckbox, firstRow);
toggle(secondCheckbox, secondRow);
toggle(thirdCheckbox, thirdRow);
toggle(fourthCheckbox, fourthRow);
toggle(fifthCheckbox, fifthRow);

5 Answers

Hey Devin,

Maybe I can help! I was looking at your JS code and in your toggle function you are calling the event click. Maybe calling the event change instead? For example:

var toggle = function(checkbox, tablerow) {
  $(checkbox).change(function () {
    // your code
  });
};

It is looking for the check to change to fire off that event and handle the callback function. Also the jquery .toggle is a method to be called on an jQuery object. Since it is a method, and not a property, you will need to end it with () to call the method on the object. For example:

var toggle = function(checkbox, tablerow) {
  $(checkbox).change(function () {
    tablerow.toggle();
  });
};

That should work. However, you rows and checkbox are not aligned numerically so when you click on the first checkbox nothing will happen, but on the rest the rows should go away. Row 5 as of now will always be there.

Hope this helps! If you have more questions let me know, and maybe I can help.

Matt

Devin Gray
Devin Gray
39,261 Points

I don't want the first row to be toggled, it's supposed to be that way.

Okay so I've been looking up more examples and trying to figure out how to toggle the checkbox so it removes the corresponding table row. this is what I've come up with:

// JavaScript Document
var firstCheckbox = $('#CheckboxGroup1_1');
var secondCheckbox = $('#CheckboxGroup1_2');
var thirdCheckbox = $('#CheckboxGroup1_3');
var fourthCheckbox = $('#CheckboxGroup1_4');
var fifthCheckbox = $('#CheckboxGroup1_5');
var firstRow = $('#row1');
var secondRow = $('#row2');
var thirdRow = $('#row3');
var fourthRow = $('#row4');
var fifthRow = $('#row5');


$(document).ready(function() {
  $(checkbox).click(function(evt) {
    if (evt.target.type !== 'checkbox') {
      checkbox = $(":checkbox", this);
      checkbox.attr('checked', !checkbox.attr('checked'));
      checkbox.change();
    }
  });
});
var toggle = function(checkbox, tablerow) {
  $(checkbox).change(function() {
    if($(this).attr("checked")) {
      tablerow.hide();
    } else {
      tablerow.show();
    }
  });
});

toggle(firstCheckbox, firstRow);
toggle(secondCheckbox, secondRow);
toggle(thirdCheckbox, thirdRow);
toggle(fourthCheckbox, fourthRow);
toggle(fifthCheckbox, fifthRow);

But it still isn't working. I'm wondering if I'm going about this all wrong.

I will look into a little bit more in depth, but on first pass it appears that some of your code is is the global scope and other parts are in the function callback on the ready event, but it is hard to track the semi-colons and brackets in this form. Try, while I try to figure out more so I can try to help to do something like this:

$(document).ready(function () {

  // All your code goes here

});

Also just putting it in self-executing anonymous function like:

(function (){

  // All your code goes here
})();   

Both ways will keep your JS outside of the global scope. Hope this helps, but I will look into more then just a quick glance.

Devin Gray
Devin Gray
39,261 Points

Thanks Matt, I'll try that. I'll keep working on it and see what I get tomorrow.

I was able to get it to work by just doing this:

var firstCheckbox = $('#CheckboxGroup1_1');
var secondCheckbox = $('#CheckboxGroup1_2');
var thirdCheckbox = $('#CheckboxGroup1_3');
var fourthCheckbox = $('#CheckboxGroup1_4');
var fifthCheckbox = $('#CheckboxGroup1_5');
var firstRow = $('#row1');
var secondRow = $('#row2');
var thirdRow = $('#row3');
var fourthRow = $('#row4');
var fifthRow = $('#row5');


var toggle = function(checkbox, tablerow) {
  $(checkbox).change(function() {
   tablerow.toggle("slow");
  });
};

toggle(firstCheckbox, firstRow);
toggle(secondCheckbox, secondRow);
toggle(thirdCheckbox, thirdRow);
toggle(fourthCheckbox, fourthRow);
toggle(fifthCheckbox, fifthRow);

I removed the $(document).ready and the click event add right after that. Also, changed the logic in the change callback to use toggle slowly. I am not sure if that is the effect your looking for, but for me this works. I would recommend wrapping your JS in the self-executing anonymous function to keep from cluttering the global scope, that could become an issue with larger projects. I hope this helps!

Matt

Devin Gray
Devin Gray
39,261 Points

Great! It works! Thanks so much for your help Matt! One last question. I also want the check all and uncheck all buttons to, well, check and uncheck all of the options. I was thinking of putting each group of variables into an array and running a for each loop, and for each index in the array, if its value is unchecked, and you're pressing the check all button, make it checked. and vice versa. Would that work?

I know I'm asking a lot of you, I was just curious you're much better at this than I am.

I am happy I was able to help! I thinking there is an easier way in jQuery to use the button for check and uncheck rather then using arrays and loops. I did a quick run at it this morning and there is a solution that worked for me:

$("#check-all").on("click", function () {
  $("label > input").prop("checked", true);
  $("tr").not("[id='row1']").toggle("slow");
});

In short I add the event listener of click to the button using its id (I change it from Check All to check-all, because the space would through jQuery off) and then I targeted the check boxes using a CSS child selector, but I do recommend using a class attribute on the checkboxes you want to target in your JS program for targeting simplicity, for example:

<input class="row-toggle" type="checkbox" /> 

And then in stead of $("label > input") you could use $(".row-toggle") and jQuery will get all of those checkbox fields you want to target. Then I have it get all the tr (table rows) but not the one with the id of row1 sinceI remember you saying that it shouldn't go away.

You will want to do the reverse in order to uncheck all using the click event for that button.

Any other questions please ask! I enjoy helping. Also, I am not much better I just have spent many many many many hours getting JS errors in my programs and have asked tons of questions! Keep up the work and it will click more and more before you know it!

No problem! I am glad I can help! Just keep plugin away at JS and the rest will come. Like I said I have had many many many many console errors, and by failing I learned. Also, I am lucky enough to work at a company with really smart developers who have helped me along the way. I have found out (the hard way) learning programing and a language is not a 6 month thing, but a skill that just develops over time by building things that do not work, and figuring how to make them work. Just remember google is a developer's best friend, the most experience guys at my work have to use it sometimes to help them solve a problem. I wish you luck with your job evaluation! If you have more questions let me know, and we can figure it out together!

Devin Gray
Devin Gray
39,261 Points

@Matthew Thank you so much for all your help! I finally got what I was looking for thanks to your help. I added a class of .checked to all of the checkboxes, and I made it so that only the title bar displays when you hit the "Check All" button. Also I changed each button from toggle() to hide() and show() respectively because otherwise whats the point of having two buttons. Here's my final code.

var firstCheckbox = $('#CheckboxGroup1_0');
var secondCheckbox = $('#CheckboxGroup1_1');
var thirdCheckbox = $('#CheckboxGroup1_2');
var fourthCheckbox = $('#CheckboxGroup1_3');
var fifthCheckbox = $('#CheckboxGroup1_4');
var firstRow = $('#row1');
var secondRow = $('#row2');
var thirdRow = $('#row3');
var fourthRow = $('#row4');
var fifthRow = $('#row5');


var toggle = function(checkbox, tablerow) {
  $(checkbox).change(function() {
    tablerow.toggle("slow");
  });
};

toggle(firstCheckbox, firstRow);
toggle(secondCheckbox, secondRow);
toggle(thirdCheckbox, thirdRow);
toggle(fourthCheckbox, fourthRow);
toggle(fifthCheckbox, fifthRow);

$('#checkAll').on('click', function() {
  $('.checked').prop("checked", true);
    $('tr').not("[id='row0']").hide('slow');
});
$('#uncheckAll').on('click', function() {
  $('.checked').prop("checked", false);
  $('tr').not("[id='row0']").show('slow');
});

I'm not going to lie, this was one part of an evaluation for a job in my area, I thought I new JS and jQuery but it was harder than I thought getting the logic down and knowing when and how to use what method. Thankfully you did help in a way where you didn't do everything for me and I was able to figure out a lot and understood everything that you wrote. If you were near Van Nuys, CA I'd have them offer the job to you instead lol.

I appreciate all your help, and I can't wait to keep learning! Finally getting it right was very rewarding. I appreciate all your help!