3

I have a collection (Generic List) of objects being populated outside the model of a MVC view, and need to show a checkbox for each item in the list.

This works fine for that:

@foreach (Admin_Permission perm in ViewBag.PermissionList)
        {                
            @Html.CheckBox(perm.PermissionKey, new {Value=perm.PermissionID})  @perm.PermissionDesc
            <br>            
        }

That displays the checkboxes one per row... and there are about 50 of them, so it wastes a LOT of space, since each one's description is only about 10 characters or so.

In the past I would use a CheckBoxList with columns set to 5 for this... but that feature seems to be missing with MVC... so I need to figure out a way to do the same thing here somehow. I have played with using a for loop and counting columns and adding etc as we count thru the objects, but it does not seem to take. Always get errors where razor does not like the markeup for closing a TD and starting a new one inside a if statement.

So... the million dollar question is, how the heck do we do this properly in MVC? It seems to me I must be missing something. Its such a stupid problem to have that I must be overlooking something simple. Anyone?

David Borneman
  • 107
  • 1
  • 8
  • One more comment. I tried using the open source CheckBoxListFor<>, but that only works if your objects are included in the views model... these are not, and cannot easily be integrated in to the model the view is based on. – David Borneman Feb 02 '15 at 23:41
  • You can always use css. For example, enclose each checkbox/label in a div with `float:left; width:20%;`. Note `CheckBox` is a helper for rendering a checkbox associated with a `boolean` property, which clearly your not doing, so you may as well manually add the html and reduce your html substantially. And _how the heck do we do this properly in MVC?_ Base your views on view models (not data models) –  Feb 02 '15 at 23:54
  • Thanks Stephen. I never thought to extend the model by creating another model outside the DAL. Ill play with that idea. I think that will fix me up proper. Thanks! – David Borneman Feb 03 '15 at 00:57

3 Answers3

9

The simple way is to wrap your checkboxes in an element (usually a div), float the element to the left and give it a maximum width. That way they will flow in columns.

.check-container {
  float: left;
  width: 33%;
}
<div class="check-container">
  <input type="checkbox" id="check1">
  <label for="check1">Checkbox 1</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check2">
  <label for="check2">Checkbox 2</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check3">
  <label for="check3">Checkbox 3</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check4">
  <label for="check4">Checkbox 4</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check5">
  <label for="check5">Checkbox 5</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check6">
  <label for="check6">Checkbox 6</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check7">
  <label for="check7">Checkbox 7</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check8">
  <label for="check8">Checkbox 8</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check9">
  <label for="check9">Checkbox 9</label>
</div>
<div class="check-container">
  <input type="checkbox" id="check10">
  <label for="check10">Checkbox 10</label>
</div>

So your Razor syntax is something like this:

@foreach (Admin_Permission perm in ViewBag.PermissionList)
{       
    <div class="check-container">         
        @Html.CheckBox(perm.PermissionKey, new {Value=perm.PermissionID})  
        <label>@perm.PermissionDesc</label>
    </div>
}
DavidG
  • 113,891
  • 12
  • 217
  • 223
  • Got it. I am not a CSS guru :/ - Been stuck on fairly old tech for years, and had no idea how that really worked with the floating and width. Makes perfect sense tho... ill give that a try, as well as Stephens extending the model idea. Between the 2 of those I think ill be set. Thanks much! – David Borneman Feb 03 '15 at 00:58
1

With bootstrap this is pretty easy to achieve, simply place your checkbox inside col-md-3 col-sm-3 col-xs-3 to get 4 columns for example:

@foreach (Admin_Permission perm in ViewBag.PermissionList)
        {     
<div class="col-md-3 col-sm-3 col-xs-3">           
            @Html.CheckBox(perm.PermissionKey, new {Value=perm.PermissionID})  @perm.PermissionDesc
           </div>        
        }
JustLearning
  • 3,164
  • 3
  • 35
  • 52
0

Project your data into the right structure first.

Best to do that in the controller using a model, but can be done in the view.

@{ 
  // linq projection for creatin a 5 items per row table
  // permissions are projected into a new object where the row number and cell nummer are calculated
  // then groupby is used to group elements per row
  var table=ViewBag.PermissionList
        .Select( (v,i)=>new { row=i/5, col=i^5,value=v} )
        .GroupBy( g=> g.row);
 }

@foreach(var row in table)
{
    <tr>
    foreach(var col in row){
        <td>
        @Html.CheckBox(col.value.PermissionKey, new {Value=col.value.PermissionID})  @col.value.PermissionDesc
        </td>
    }

    // todo: fill empty cells when the last row does not contian 5 elements.        
    </tr>
}

note: did not test the razor code, contains probably syntax problems

Martijn
  • 1,440
  • 11
  • 18
  • Not a use full comment, question is how to project permissions into a 5 columns structure, up to the developer to use div or tables. besides that, "tables are for data", and it seams that here perimission data is displayed to the user. – Martijn Feb 03 '15 at 00:02
  • It is a perfectly useful comment. Using tables for layout is considered to be bad practice. Lots of reasons why, here are some http://stackoverflow.com/questions/83073/why-not-use-tables-for-layout-in-html – DavidG Feb 03 '15 at 00:05
  • Table is used for data in this usecase and not for layout. – Martijn Feb 03 '15 at 00:07
  • No, he specifically says he is using it for layout as he is wasting space. – DavidG Feb 03 '15 at 00:07
  • This is a table on a page with permissions, that is correct use for a table. Tables for layout is the case where the header, footer and content of the page are managed using a table. This is a perfect valid "cross"-table containing permission data. Reference: http://stackoverflow.com/questions/82391/should-tables-be-avoided-in-html-at-any-cost#82402 – Martijn Feb 03 '15 at 00:08
  • 1
    So you link an answer that says use tables for tabular data when OP isn't using tabular data? – DavidG Feb 03 '15 at 00:11
  • I agree on (+1) that. the css solution is indeed elegant. – Martijn Feb 03 '15 at 00:14