To tackle each problem effectively
- CSS does not affect the label (it does not change the background)
Upon inspecting the HTML you are generating, it becomes evident that the CheckBoxFor()
helper generates two inputs - <input type="checkbox" ..>
followed by <input type="hidden" ..>
and finally the <label>
element. Your CSS selector (input[type="checkbox"] + label
) is searching for a label element right after a input[type="checkbox"]
, but due to the hidden input in between, this label doesn't exist as expected. One option is to utilize a Following-sibling combinator
<div>
@Html.CheckBoxFor(m => m[i].checkExport)
@Html.LabelFor(m => m[i].checkExport)
</div>
input[type="checkbox"] ~ label {
....
}
View fiddle for reference
- The label for the tag does not point to the checkbox because it cannot define the id of the checkbox
This issue arises from html helpers adhering to previous HTML specifications.
The id attribute generated by the html helpers is derived from the property name, yet to prevent conflicts with jQuery, any occurrences of '.', '[', or ']' characters are replaced with an underscore ('_'). In your scenario, '[0].checkExport' would transform into '_0__checkExport'.
In HTML 4, an id attribute was required to commence with a letter, rendering such markup invalid and consequently prompting the html helper to omit the attribute in the generated markup. Review the source code here, specifically targeting this section of the code
if (!Html401IdUtil.IsLetter(firstChar))
{
// the first character must be a letter
return null;
}
- The label is non-clickable
This issue ties back to point 2 since an id attribute isn't being generated for the checkbox, thereby causing the label element to lack a valid 'for' attribute linking it to the associated checkbox.
A possible solution involves implementing a view model containing a property for your collection, like so
public class MyViewModel
{
public List<myModel> MyCollection { get; set; }
}
Within the view
@model yourAssembly.MyViewModel
....
for (int i= 0; i < Model.MyCollection.Count; i++)
{
@Html.CheckBoxFor(m => m.MyCollection[i].checkExport)
@Html.LabelFor(m => m.MyCollection[i].checkExport)
Subsequently, your inputs will be furnished with id attributes and the label will encompass a corresponding 'for' attribute linked to the checkbox, rendering it 'clickable'.
<input type="checkbox" id="MyCollection_0__checkExport" name="MyCollection[i].checkExport" ../>
...
<label for="MyCollection_0__checkExport">checkExport</label>