From array create same number of checkboxes using the id's


#1

Ok I have a table where 3 of the columns at this stage can be additional columns, so they are there but as default then need to be hidden. What Im trying to do then is when the user opens up a modal there should be the same number of checkboxes using the id’s of the colums, and there the user has the option to make those colums visible.

So here is my table, well its a pretend one for now.

<table>
    <tr id="a" class="hide"><td>test</td></tr>
    <tr id="b" class="hide"><td>test</td></tr>
    <tr id="c" class="hide"><td>test</td></tr>
    <tr id="d"><td>test</td></tr>
    <tr id="e"><td>test</td></tr>
    <tr id="f"><td>test</td></tr>
</table>

And this is my map function to look for the class that equals hide and store the id values in an array

var ids = $('table .hide').map(function(){
    return this.id
}).get();

console.log(ids)

That works fine, but ideally I need to also use css to make those with hide display:none

But what I know need to do is use those id’s stored in that array to create the same number of checkboxes with those id’s attached to each one, and the append them to a div in the modal.

Can someone help me with this bit which is the first bit, Ive found something like below, but not sure how to use the array in the for loop to create the checkboxes and add the id’s.

var inputs = [], i
for(i = 0; i < 10; i++)
  inputs.push('<input type="checkbox" id="ck'+ i +'"/>')
$('#checkboxWrapper').append(inputs.join(''))

Then when they select any of the checkboxes, and click ok I want the colums to appear visible once the modal is closed, but thats for the next function which will be activated on click of the OK button by an onclick function which it knows from the button id


#2

Hi @multichild, you might map the hidden rows to checkboxes directly; actually you don’t even need IDs then (not for this functionality at any rate):

var $hiddenRows = $('table .hide')

var $checkboxes = $hiddenRows.map(function () {
  return $('<input type="checkbox" />').get(0)
}).appendTo('#checkboxWrapper')

$('.modal-close').click(function () {
  $checkboxes.each(function (index) {
    $hiddenRows.eq(index).toggleClass('hide', !this.checked)
  })
})

#3

Ah I see what youve done, and its a little different. On load the jquery needs to look for the class hide and then hide those columns, but ive found its not as easy as there no id’s on the actual th but instead on the p inside it as below.

@Html.TableHeaderFor(model => model.Actions, "Recommendation", Model.DistinctColumnValues,
Html.LocalisedText("lblRecommendation", "lblActions_Recommendation", TheSystem.Enums.SystemComponent.TheSystem, "text title textSizeStandard alignCenter"), cssClass: "hide")

which renders as 

<th class="hide" data-column-name="Recommendation" data-datatype="" style="vertical-align:middle;"><p class="text title textSizeStandard alignCenter text" id="lblRecommendation">Recommendation</p></th>

So what I need to do is those columns that have hide as a class on the p to hide the th, and then I suppose use data-column-name which is what I need to create the checkboxes in the modal once its opened.

Umm,

So the first bit is hiding the table th’s and equally the td’s of the same id.

Then when the user clicks a button

    $("#btnViewOptions").click(function() {
        LoadViewOptionsForm(true, true);
    });

function LoadViewOptionsForm() {
    $('#mdlColumnVisibility').modal('show');
}

And in there the checkboxes are created using the ids gathered. Then the user can select a checkbox to reveal that th and td again, which should appear after they close the modal once they click the OK button as below

@Html.LocalisedButton("btnSubmitCategoryVisibility", "btnOkay", SystemComponent.Shared, additionalHtmlAttributes: new Dictionary<string, string>() { { "data-dismiss", "modal" } })

$("#btnSubmitCategoryVisibility").click(function() {
        
    });

God I hope that makes sense.


#4

Ok good news this works perfectly in counting the number of hide classes and then rendering out those checkboxes in the div once the modal has popped up. And it would be great if those th’s could hide as the page renders.

    var $hiddenRows = $('table tr .hide');
    var $hiddenRowsID = $('table tr .hide').data("column-name");

    console.log($hiddenRowsID);

    var $checkboxes = $hiddenRows.map(function () {
        return $('<input type="checkbox" />').get(0);
    }).appendTo('#checkboxWrapper');

    $('.modal-close').click(function () {
        $checkboxes.each(function (index) {
            $hiddenRows.eq(index).toggleClass('hide', !this.checked);
        });
    });

So what I need to happen now is use belows value to use as the id of the checkbox and the text alnogside of the checkbox to give it reference.

data-column-name=""

var $hiddenRowsID = $('table tr .hide').data("column-name");

    console.log($hiddenRowsID);

Is then used as the checkbox id and also the text alongside it, so that when they select a checkbox to ask for that column to be visible, they select it and its visible once the modal is closed after clicking the Ok button above


#5

Im not 100% sure as I cant check it outside of work, but Im wondering if something like this would work…

var $hiddenRows = $('table tr .hide');
var $hiddenRowsID = $('table tr .hide').data("column-name");

var $checkboxes = $hiddenRows.map(function () {
var $checkboxesID = $hiddenRowsID.map(function () {
return $('<input type="checkbox" id="checkboxesID" /> checkboxesID').get(0);
})}).appendTo('#checkboxWrapper');

#6

Not sure what you mean… can’t you just add those classes to the initial page markup?

Yes, data attributes are a good option for this. For example:

<tr 
  id="a" 
  class="hide"
  data-checkbox-id="checkbox-a"
  data-checkbox-label="Checkbox a"
><td>test</td></tr>
...
var $checkboxes = $hiddenRows.map(function () {
  var $checkbox = $('<input />', {
    type: 'checkbox',
    id: this.dataset.checkboxId
  })

  return $('<label />')
    .text(this.dataset.checkboxLabel)
    .append($checkbox)
    .get(0)
}).appendTo('#checkboxWrapper')

(whoops, x-post)


#7

Oh sorry, didnt realise we both replying at the same time lol.

Yes there sort of three things that need to happen.

  1. the th’s with the class hide need to be hidden on page load
  2. then loop through those hide classes to count the number of them to re-create the same number as checkboxes
  3. then also add the data-column-name value to the checkboxes id and use it as text outside the input

Thats the first part.

Then when a user clicks to open a modal it reveals the checkboxes, and if they select one, that one corresponds with one of the hidden th’s to reveal it on close of the modal.

Thats strange, have had a beer and can explain it better :slight_smile:

Thanks for helping again though m3g4p0p, much appreciate it…


#8

But they do have that class on page load? Then just hide them with CSS…

.hide {
  display: none;
}

The other points should be covered with the above snippets – here’s a fiddle.

Everything works better with a beer. :-) Cheers!


#9

Thank you the creation of the checkboxes works perfectly, its a very minor point, but where can add a
so I can make each label on a separate line, don.t seem to be able to get it working.

Anyway, I cant get the selected checkboxe to make the th reappear, this is my code below, slightly different from yours but it does work.

function GetHideAdditionalColumns() {

    var $hiddenRows = $('table tr .hidden');

    var $checkboxes = $hiddenRows.map(function() {
        var $checkbox = $('<input />',
            {
                type: 'checkbox',
                id: this.dataset.columnName
            });

        return $('<label />')
            .text(this.dataset.columnName)
            .append($checkbox)
            .get(0);
    }).appendTo('#checkboxWrapper').find('input');



    $('#btnSubmitCategoryVisibility').click(function () {
        $checkboxes.each(function (index) {
            $hiddenRows.eq(index).removeClass('hidden', !this.checked);
        });
    });
}

This is what the column looks like in its entirity

<th class="hidden" data-column-name="Recommendation" data-datatype="" style="vertical-align:middle;"><p class="text title textSizeStandard alignCenter text" id="lblRecommendation">Recommendation</p></th>

So then when the modal opens and the checkboxes are already there, its like this with the three created correctly.

<div class="modal-body text textSizeStandard" style="max-height:500px; overflow-y:scroll">
<div id="checkboxWrapper">

<label>Recommendation<input type="checkbox" id="Recommendation"></label><label>AuditComments<input type="checkbox" id="AuditComments"></label><label>QuestionnaireArea<input type="checkbox" id="QuestionnaireArea"></label></div>

</div>

But then on click of #btnSubmitCategoryVisibility, the function is called but it doesnt make the column re-appear, the class hidden stays there. In the sxample I have changed it from toggle to remove, but thats just me trying to get it working, it was set to toggleClass originally


#10

Just set them to display: block,or wrap them in divs or a list or something… actually I think a list would make sense here semantically.

Hm… I don’t see an immediate problem in your code. It might have to do with where and when you are calling GetHideAdditionalColumns()… BTW I’m a bit confused about the nature of that function. The name suggests it would return something (which it doesn’t), and it starting with a capital letter suggests it’s a constructor function (which again is at odds with the name).

So can you provide a fiddle that demonstrates the problem, or the minimum code required top reproduce it – especially the part where GetHideAdditionalColumns() is invoked?


#11

Yes there something a miss, but the good news in the function below I do see the alert

    $('#btnSubmitCategoryVisibility').click(function () {
        alert("hello");
        $checkboxes.each(function (index) {
            $hiddenRows.eq(index).removeClass('hidden', !this.checked);
        });
    });

But in the next post I will post the full cycle and explain


#12

This is within a partial that’s called from the main index page, all is good here, and as you can see the cssClass added to three of the table headers

<thead>
<tr>

@Html.TableHeaderFor(model => model.Actions, "ResponsiblePerson", Model.DistinctColumnValues,
Html.LocalisedText("lblResponsiblePerson", "lblActions_ResponsiblePerson", TheSystem.Enums.SystemComponent.TheSystem, "text title textSizeStandard alignCenter"))
            
 <!-- #region Additional Columns -->
            
@Html.TableHeaderFor(model => model.Actions, "Recommendation", Model.DistinctColumnValues,
Html.LocalisedText("lblRecommendation", "lblActions_Recommendation", TheSystem.Enums.SystemComponent.TheSystem, "text title textSizeStandard alignCenter"), cssClass: "hidden")

@Html.TableHeaderFor(model => model.Actions, "AuditComments", Model.DistinctColumnValues,
Html.LocalisedText("lblAuditComments", "lblActions_AuditComments", TheSystem.Enums.SystemComponent.TheSystem, "text title textSizeStandard alignCenter"), cssClass: "hidden")
            
@Html.TableHeaderFor(model => model.Actions, "QuestionnaireArea", Model.DistinctColumnValues,
Html.LocalisedText("lblQuestionnaireArea", "lblActions_QuestionnaireArea", TheSystem.Enums.SystemComponent.TheSystem, "text title textSizeStandard alignCenter"), cssClass: "hidden")
            
 <!-- #endregion -->           

@Html.TableHeaderFor(model => model.Actions, "Status", Model.DistinctColumnValues,
Html.LocalisedText("lblStatus", "lblContracts_Status", TheSystem.Enums.SystemComponent.TheSystem, "text title textSizeStandard alignCenter"))

</tr>
</thead>

and in general.css

.hidden {
    display: none;
}

So the page loads and this js file is called, and as you can see its all in there, thats all of the js

$(function() {

    UpdateTableData(PageName, "tblActions");

    $("#btnViewOptions").click(function() {
        LoadViewOptionsForm(true, true);
    });

    var $hiddenRows = $('table tr .hidden');

    var $checkboxes = $hiddenRows.map(function () {
        var $checkbox = $('<input />',
            {
                type: 'checkbox',
                id: this.dataset.columnName
            });

        return $('<label />')
            .text(this.dataset.columnName)
            .append($checkbox)
            .get(0);
    }).appendTo('#checkboxWrapper').find('input');

    $('#btnSubmitCategoryVisibility').click(function () {
        alert("hello");
        $checkboxes.each(function (index) {
            $hiddenRows.eq(index).removeClass('hidden', !this.checked);
        });
    });

});

function tblActions_TableUpdateCallBackFunction() {
    
}

function LoadViewOptionsForm() {
    $('#mdlColumnVisibility').modal('show');
}

So the button below uses a click function to open the modal which has the checkboxes already populated on load of the main page.

@Html.LocalisedButton("btnViewOptions", "lblViewOptions", SystemComponent.TheSystem, cssClass: "positionTopRight textSizeStandard")

Again this is all fine, its just when the user selects a checkboxes clicks ok as below and i get the alert but nothing changes in the columns, the class hidden stays there.

@Html.LocalisedButton("btnSubmitCategoryVisibility", "btnOkay", SystemComponent.Shared, additionalHtmlAttributes: new Dictionary<string, string>() { { "data-dismiss", "modal" } })

I hope thats ok all that


#13

I’m thinking it must be that the table with the hidden class is on the main page, and the checkboxes are in the modal, and when it closes there must be a communication breakdown where it cant control the class of the table. In your example everything seems to be flat, as in all at the same level, no modal pops up, could that be the reason


#14

I think you would be better using console.log() instead of alert(). It has been a while since I’ve used alert for debugging but IIRC there were times it caused problems by interfering with how the code would have run without it.


#15

Sure yes I understand, I’ll use that when i get in tomorrow. very drustrating though as m3g4p0p had nailed it with his.


#16

Ok good news, Ive got it working…

    var $hiddenRows = $('table th').filter(":not(:visible)");

    var $checkboxes = $hiddenRows.map(function () {
        var $checkbox = $('<input />',
            {
                class: 'ml-2',
                type: 'checkbox',
                'data-column-name': this.dataset.columnName
            });

        return $('<div style="width:100%; clear:both;" />')
            .text($(this).find("p").text())
            .append($checkbox)
            .get(0);
    }).appendTo('#checkboxWrapper').find('input');

    $('#btnSubmitCategoryVisibility').click(function () {
        $checkboxes.each(function (index) {
            $('table th[data-column-name="' + $(this).data("column-name") + '"]').toggle(this.checked);
        });
    });

So that shows the relevant th, so am wondering now how can I target the td values in the same column. I think ideally I use the column number and use that to target the td’s within that column, but can think how to do it


#17

Its not right I know, and probably way to simplistic, but im thinking something along these line, but Im not sure using index in this case is right.

        $checkboxes.each(function (index) {
            $('table th[data-column-name="' + $(this).data("column-name") + '"]').toggle(this.checked);

            $('table tr td:nth-child(' + (index) + ')').toggle(this.checked);
        });

But its not the index of the checkboxes, its the index of the th I need.

so select all of the tables TH elements

then find the index of the TH that matches the column-name, and then use nth-child that way, but I cant work it out.

Maybe this is getting there, but what do I push into var columnSelected, as the console.log is showing the correct number of th, as I need the column number to then use as :nth-child which is commented out in the function below:

$checkboxes.each(function () {
  $('table th[data-column-name="' + $(this).data("column-name") + '"]').toggle(this.checked);
});
var elem = $('table th');
elem.each(function(index) {
if ($('[data-column-name="' + $(this).data("column-name") + '"]' ===
  $(this).data("column-name") + '"]').toggle(this.checked)) {
  $('table tr td:nth-child(' + index + ')').show(this.checked);
  console.log(index);
  }
});

I sort of get results, but its not right as console log shows the number value of each th, but what I want is the number of the th that has the same value as the selected checkbox/s


#18

I’m not familiar with ASP.NET (?), but if the tr itself has the hidden class as in your OP, the selector would be

$('table tr.hidden')

Using regular selectors is much faster than those custom jQuery selectors like :hidden and :visible, so better use those where possible.

As long as they all have the same colspan, this should do the trick:

function getColumn (selectorOrElement) {
  var $tableCell = $(selectorOrElement)
  var index = $tableCell.index() + 1

  return $tableCell
    .closest('table')
    .find('td:nth-child(' + index + ')')
}

// Use like e.g.
getColumn('[data-column-name="something"]').show()
// Or inside a jQuery method such as elem.each() above:
elem.each(function () {
  getColumn(this).show()
})

closed #19

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.