|
|
Comments and Discussions
|
|
 |
|

|
Great article, Mikhail! You might remember me mentioning that I'll be creating a library of html helpers for TwitterBootstrap. It is available now here. I also gave you credit there!
|
|
|
|

|
That's awesome! I definitely remember about your project, Dmitry, so I'll check out your article soon, thanks for rating!!!
|
|
|
|

|
Hello,
Nice post,
I have a question though. Where are the pictures of the results. These are needed to attract more viewers.
- Deviant
|
|
|
|

|
Yes! That is a great idea indeed. I figured live examples on the official site should be enough, but I agree some screenshots would never hurt!
|
|
|
|

|
Extension looks (and works) great,but have one question:
Now i want to choose items,whose type is not complex class like your "City" from example,but for simple string.
In that case i don't have any Id/Value pair in element,each element of that list is one simple string.
Can your extension handle with something like that (in any example i saw pair key/value is required).
Thanks in advance for any answer.
Regards,
Kamil
|
|
|
|

|
Hi Kamil,
To do what you want you can simply ajust the 'complex' class to have only one string property and use that for both value and text of the list, e.g.:
public class YourClass {
public string Name { get; set; }
}
Then call it like that:
@Html.CheckBoxList("YourClass",
model => model.ListOfYourClass,
property => property.Name,
property => property.Name,
model => null)
I hope that'll work for you!
|
|
|
|

|
Has anyone seen the checkbox split from the label? For me the checkbox appears with the label underneath. I am doing any special formatting. When I view source and copy n paste the code nto a plain html file it looks fine but on my site it's split? anyone?
|
|
|
|

|
You can uses developer tools in Internet Explorer to identify what style are applied on every item. And you can even uncheck a checkbox so that that style won't be applied and immediatly see the resulting page.
It all depends on the content of the CSS style sheet.
Philippe Mori
|
|
|
|

|
That can only happen if the something is limiting the width of area where your checkboxes are generated. Check html source and make sure there is enough space for both label's text and checkbox.
|
|
|
|

|
Great addition! Unfortunately, a class named "Position" is a first-class citizen in my project and it conflicts w/ your "Position" enum. Why is your "Position" enum in the global namespace?
|
|
|
|

|
No particular reason, Eldar, it was just convenient at the moment when it was coded - no need to define @using statement on the views. I am confident though, that it was not too forward-looking decision)) It should indeed have it's own namespace.
Anyway, I moved all enums/classes to their own namespace MvcCheckBoxList.Model, grab that new dll here (for .NET 4.5 only):
https://dl.dropbox.com/u/37444966/CodeProject/MvcCheckBoxList.v.1.4.4.4.dll[^]
(if you use .net 4.0, let me know)
So now you'd need also define this on your view:
@using MvcCheckBoxList.Model
I also pushed that change to the dev branch on Github.
|
|
|
|

|
Hi,
I have a little problem with posting data to the controller.
I have class RoleViewModel and GroupAddViewModel that has property which is list of RoleViewModel objects.
Binding to CheckBoxList works fine, but if I post model with data back to the controller I have ModelState.IsValid always set to false because of conversion from string to RoleViewModel problem. So it looks like CheckBoxListFor tries to pass array of strings in model object instead of collection of RoleViewModel objects.
Do you have any solution (except use of ModelState.Clear()) to work-around this issue? Or am I doing sth. wrong?
Here is my code:
1. View model:
public class GroupAddFacadeViewModel
{
public GroupAddViewModel Group { get; set; }
public IEnumerable<RoleViewModel> Roles { get; set; }
}
2. RoleViewModel:
public class RoleViewModel
{
public int RoleID { get; set; }
public string Name { get; set; }
}
3. GroupViewModel:
public class GroupAddViewModel
{
[DisplayName("Name")]
public string Name { get; set; }
[DisplayName("Description")]
public string Description { get; set; }
[DisplayName("Roles")]
public IEnumerable<RoleViewModel> SelectedRoles { get; set; }
}
4. Controller:
[HttpPost]
public ActionResult Add(GroupAddFacadeViewModel model, string[] Roles)
{
if (ModelState.IsValid)
{
}
}
(Array of roles is posted correctly)
Best regards,
Max
|
|
|
|

|
Hey Max,
This extension always posts an array of strings (it should be a part of a model object), since there is no other good way as of now, that is how html works...
To get your code working, instead of posting the whole view model to controller, try create a property on a view model that contains only things you need for your controller.
Try the following:
Adjust your view model like this:
public class GroupAddFacadeViewModel {
public GroupAddViewModel Group { get; set; }
public IEnumerable<RoleViewModel> Roles { get; set; }
public PostedStuff PostedStuff { get; set; }
}
public class PostedStuff {
public GroupAddViewModel Group { get; set; }
public string[] Roles { get; set; }
}
Then change your controller like this:
[HttpPost]
public ActionResult Add(PostedStuff postedStuff) {
if (ModelState.IsValid) {
}
}
Then make sure only properties of 'PostedStuff' are included in the form being posted.
This recommendation is based on the documentation here:
http://mvccbl.com/Home/Documentation[^]
I hope that helps!
Regards,
Mikhail
|
|
|
|

|
Hi Mikhail,
Thanks a lot for help.
It works fine now.
Best regards
Max
modified 3 Mar '13 - 4:43.
|
|
|
|

|
Awesome, I'm glad to hear that!
I believe that separating view model into separate ones will make everything more error-prone, since you'll always control what you post and what you don't, especially if your model/view will get more complicated e.g. if you include multiple forms on the same view, or have forms inside of the foreach loop, etc. I realized after few years of working with MVC3 and MVC4, it just makes life easier in the long run, even if it seems a bit more complicated at first.
Anyway, Good Luck with you project!
Mikhail
|
|
|
|

|
I am using the CBL control to select filters for some displayed data. Is there an easy way to make the checkboxes automatically submit the form when checked/unchecked?
|
|
|
|

|
The easiest way is to use jquery function like this:
$('input:checkbox').change(function() {
$('#YOUR_FORM_ID').submit();
});
This will submit your form whenever any checkbox selection changes, so you might need to adjust jquery selector to target only required subset of checkboxes.
|
|
|
|

|
Dear All,
Can you please provide the steps for how to use this,
as i am new to MVC. I have add the reference of the dll in my project but in
View Model it is not allowing me to use the CheckBoxList plz help it's very urgent.
Thanks
|
|
|
|

|
Hi Prashant,
To make sure it is installed correctly I would suggest installing it from NuGet package manager[^], instead of adding the reference manually because the .dll attached to this article is for .NET 4.0 and MVC3 only.
If you have an MVC4 project with .NET 4.5 you need to install latest beta version, and the only way to do so is to install it from NuGet, you need to run this command in NuGet package manager console:
Install-Package MvcCheckBoxList -Pre
Alternatively, if you don't want to use NuGet, you can download source project from Github[^], build it and copy MvcCheckBoxList.dll manually.
|
|
|
|

|
I want to thank you for building this, it was much needed. I've gotten it to display the check boxes correctly, but I'm having a difficult time returning the posted values.
I went over the other threads with you and Alex Brown and my scenario is similar but I have an extra model which I think is causing the problems.
I need to pass more to the view than just the CheckBoxList data, so I've attached my CBLViewModel to a ViewData class that I pass to all views. I've looked at ALL your documentation and I still think I'm missing something somewhere.
Here are the various code snippets:
This is the view code:
@model PGO.Mvc.ViewData.OpticsItemViewData
... other HTML stuff here
<b>@Html.Label("Assign To")</b><br />
@Html.CheckBoxListFor(model => model.OpticsItemViewModel.PostedPages.PageIds,
model => model.OpticsItemViewModel.AvailablePages,
model => model.Id,
model => model.PageName,
model => model.OpticsItemViewModel.SelectedPages, Position.Vertical)
... other HTML stuff here
This is my ViewData class that passes any and all necessary data to the view:
public class OpticsItemViewData : BaseViewData
{
public OpticsItemViewData()
{
OpticsItemViewModel = new OpticsItemViewModel();
}
public OpticsItem OpticsItem { get; set; }
public List<OpticsItem> OpticsItemList { get; set; }
public SelectList PageSelectList { get; set; }
public List<Page> PageList { get; set; }
public OpticsItemViewModel OpticsItemViewModel { get; set; }
}
This is the ViewModel to be used by the CheckBoxList extension:
public class OpticsItemViewModel
{
public IEnumerable<Page> AvailablePages { get; set; }
public IEnumerable<Page> SelectedPages { get; set; }
public PostedPages PostedPages { get; set; }
}
public class PostedPages
{
public string[] PageIds { get; set; }
}
Here's part of my controller action with most of the non-CBL code stripped away. The PostedPages object is recognized Ok, but the PageIds property is always null.
[HttpPost]
public virtual ActionResult Create(
[Bind(Exclude = "Id,rowversion", Prefix = "OpticsItem")]OpticsItem model,
[Bind(Prefix = "OpticsItemViewModel")]PostedPages postedPages,
IEnumerable<HttpPostedFileBase> attachments)
{
var pageIds = postedPages.PageIds; if (pageIds == null)
throw new Exception("No Pages were selected.");
}
And finally this is the rendered HTML so you can see what needs to be done in the controller:
<input id="OpticsItemViewModel_PostedPages_PageIds4"
name="OpticsItemViewModel.PostedPages.PageIds"
type="checkbox" value="1"></input>
<label for="OpticsItemViewModel_PostedPages_PageIds4">48-Hour Optics</label><br/>
<input id="OpticsItemViewModel_PostedPages_PageIds5"
name="OpticsItemViewModel.PostedPages.PageIds"
type="checkbox" value="2"></input>
<label for="OpticsItemViewModel_PostedPages_PageIds5">Glass Substrates</label><br/>
I know I'm missing something. Any help you can provide is appreciated.
Thanks,
King Wilder
|
|
|
|

|
This always seems to happen, the moment I post an issue, I figure it out myself.
Here's my solution, I just referenced the first part of the name attribute.
This was one of the checkbox input elements:
<input id="OpticsItemViewModel_PostedPages_PageIds4"
name="OpticsItemViewModel.PostedPages.PageIds"
type="checkbox" value="1"></input>
And here's how I referenced it in my controller:
[HttpPost]
public virtual ActionResult Create(
[Bind(Exclude = "Id,rowversion", Prefix = "OpticsItem")]OpticsItem model,
OpticsItemViewModel opticsItemViewModel, IEnumerable<HttpPostedFileBase> attachments)
{
var pageIds = opticsItemViewModel.PostedPages.PageIds; if (pageIds == null)
throw new Exception("No Pages were selected.");
}
Sorry to take up the bandwidth, but I hope this helps others.
Again, thanks for making this extension.
King Wilder
|
|
|
|

|
CheckBoxListFor was not recognizing my view model. I have added the dll in my reference, Am I missing anything ?
|
|
|
|

|
Hello Mikhail
Thanks for the extension, it saved me a lot of time!
I was wondering, for each checkbox item generated how would I add an action link?
For example I have a list of modules and want the ability to click an edit link on each one:
@Html.CheckBoxListFor( x => x.PostedModules.Modules,
x => x.Modules,
x => x.ModuleID,
x => x.Title,
x => x.SelectedModules
)
Many thanks,
Michael
|
|
|
|

|
Hi Michael, thank you! I am glad it works for you!
At the moment the only way to accomplish what you want, is to use Display Templates, see example here (scroll down to 'Display templates to render html for checkbox' section):
http://mvccbl.com/Home/Examples[^]
Also note that Display Templates are only available in beta version 1.4.4.3-beta2, so if you use older version from this article, upgrade to it now:
Install-Package MvcCheckBoxList -Pre
Let me know if that works for you!
|
|
|
|

|
Thank you Mikhail I will let you know how it goes
|
|
|
|

|
I want to display the list in the following order:
1 2 3 4
5 6 7 8
I've already used Linq in the list but still it displays like this:
1 3 5 7
2 4 6 8
Thnaks.
|
|
|
|

|
Did you try to use horizontal layout (default) instead of vertical? If you'd use horizontal, than you can try to limit the width of the <div> with your CheckBoxList inside, and browser will automatically arrange them in order.
Also reply here with a code of how you initialize extension currently, so it would be easier to help you.
|
|
|
|

|
Here is the code:
The CSS of my individual checkboxes.
label
{
display:inline-block;
}
.checkbox-normal
{
display: none;
}
.checkbox-normal + label {
background-color: #fafafa;
border: 1px solid #cacece;
box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05);
padding: 9px;
border-radius: 100%;
display: inline-block;
position:relative;
}
.checkbox-normal + label:active, .checkbox-normal:checked + label:active {
box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px 1px 3px rgba(0,0,0,0.1);
width: 30px;
height: 30px;
}
.checkbox-normal:checked + label {
background-color: #e9ecee;
border: 1px solid #adb8c0;
box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05), inset 15px 10px -12px rgba(255,255,255,0.1);
color: #99a1a7;
}
.checkbox-normal:checked + label:after {
content: '\2714';
font-size: 14px;
position: absolute;
top: 8px;
left: 12px;
color: #99a1a7;
}
My Model
public class RelocationModel
{
public string Name { get; set; }
public int Id { get; set; }
public int Value { get; set; }
public bool Selected { get; set; }
}
public class PostedRelocations
{
public string[] MetaIDs { get; set; }
}
public class ViewModel
{
public IList<RelocationModel> Relocations { get; set; }
public IList<RelocationModel> SelectedRelocations { get; set; }
public PostedRelocations PostedRelocations { get; set; }
public IList<FamilySituationModel> FamilySituations { get; set; }
public IList<FamilySituationModel> SelectedFamilySituations { get; set; }
public PostedFamilySituations PostedFamilySituations { get; set; }
}
public class FamilySituationModel
{
public string Name { get; set; }
public int Id { get; set; }
public int Value {get;set;}
public bool Selected { get; set; }
}
public class PostedFamilySituations
{
public string[] MetaIDs { get; set; }
}
Now in my View
<table>
<tr>
<td>
@{
var htmlListInfo = new HtmlListInfo(HtmlTag.table, 5, new { @class = "styled_list" });
<div class="editor-label">
@Html.LabelFor(model => Model.Relocations)
</div>
<div class="editor-field">
@Html.CheckBoxListFor(model => model.PostedRelocations.MetaIDs,
model => model.Relocations,
x => x.Id,
x => x.Value,
model => model.SelectedRelocations,
new { @class = "checkbox-normal" },
htmlListInfo, null, null)
</div>
}
</td>
</tr>
</table>
The "Name" (e.g. Natural Disaster) in my model contains the description of the item in my list, while the "Value" (e.g 1) will hold the number which will be displayed as a label inside the checkbox.
What I want to do here is that I want to display the checkboxes in circles with the "Value" inside as a label and beside them would be the "Name" or the description. Would look like this:
1 Description 2 Description 3 Description
4 Desciption 5 Description 6 Description
The numbers are inside a circle (which is the checkbox) and the description beside them.
I would very much appreciate it if anyone could help me on this.
Thank you very much
|
|
|
|

|
Well first of all, to get your list aligned horizontally, you need to get rid of HtmlListInfo and call it like that:
@Html.CheckBoxListFor(model => model.PostedRelocations.MetaIDs,
model => model.Relocations,
x => x.Id,
x => x.Value,
model => model.SelectedRelocations,
new { @class = "checkbox-normal" })
This will effectively allign them like, if width is limited by wrapping div around list:
1 2 3 4
5 6 7 8
So try that first.
As for:
"The numbers are inside a circle (which is the checkbox) and the description beside them"
As of now this would be somewhat challenging to achieve and will involve heavy reliance on JQuery.
At current state of this extension the best way to customize output is to use Display Templates, see example here (scroll down):
http://mvccbl.com/Home/Examples[^]
However right now you can use Display Templates only for HtmlTag.vertical_columns and HtmlTag.table, so no horizontal layout yet. After your question, I figured that I need to add support for horizontal layout when using Display Templates, but I'll have to work on that one of those days.
Finally, since you need quite customized output, I would suggest to try to generate checkbox list manually, as I feel It'll be less difficult than making this extension work for your needs.
Anyway first try what I suggested above.
|
|
|
|

|
Controller:
public ActionResult InventorySnapshot(InventorySnapshotViewModel viewModel)
{
return ExecuteGenericAction(viewModel, x => new InventorySnapshotAction());
}
Model
public class InventorySnapshotViewModel
{
public IEnumerable<ProductAttribute> ProductAttributes { get; set; }
public IEnumerable<ProductAttribute> SelectedProductAttributes { get; set; }
}
public class ProductAttribute
{
public int ID { get; set; }
public string Name { get; set; }
}
@Html.CheckBoxListFor(x => x.ProductAttributes, x => x.ProductAttributes, x => x.ID, x => x.Name, x => x.SelectedProductAttributes)
However, SelectedProductAttributes is null during post. Other values in the form are populated. Any help is appreciated.
|
|
|
|
|

|
I'm having trouble getting the selected values into my model.
I pass in a view model that looks like:
public class NewLicenseViewModel
{
public NewLicenseModel NewLicense { get; set; }
public IEnumerable<LicensableFeatureModel> AvailableLicensableFeatures { get; set; }
}
LicensableFeatureModel is a simple:
public class LicensableFeatureModel
{
public string ID { get; set; }
public string Name { get; set; }
}
My MVC razor view looks like:
@model Licensing.Web.Models.NewLicenseViewModel
@Html.CheckBoxListFor(x => x.NewLicense.LicensedFeatures,
x => x.AvailableLicensableFeatures,
x => x.ID,
x => x.Name,
x => x.NewLicense.LicensedFeatures)
The checkboxes are appearing correctly.
However, when I post the form, my controller action receives the NewLicenseModel with other bits filled in (in other parts of form) however, .LicensedFeatures is null:
[HttpPost]
public ActionResult Create(NewLicenseModel licenseRequest)
{
}
Any idea what I've done wrong?
|
|
|
|

|
Here you go:
1) When values of selected checkboxes are posted back to controller, they are posted as an array of strings only, and cannot be mapped to a class directly, so your model:
public class NewLicenseViewModel {
public NewLicenseModel NewLicense { get; set; }
public IEnumerable<LicensableFeatureModel> AvailableLicensableFeatures { get; set; }
}
Should look like this:
public class NewLicenseViewModel {
public NewLicense NewLicense { get; set; }
}
public class NewLicense {
public string[] LicensedFeatures { get; set; }
}
2) Then first part of your CBL name (NewLicense) must match controller parameter, and second part (LicensedFeatures) must match parameter of a class NewLicense:
[HttpPost]
public ActionResult Create(NewLicense newLicense) {
var selectedValues = newLicense.LicensedFeatures;
}
3) Remember that it is very important to match the pattern above for your call to checkbox control to work (again, 'NewLicense' is a name of a property on the view model, 'LicensedFeatures' name of a property of class 'NewLicense'):
@Html.CheckBoxListFor(x => x.NewLicense.LicensedFeatures,
x => x.AvailableLicensableFeatures,
x => x.ID,
x => x.Name,
x => x.NewLicense.LicensedFeatures)
Please see more examples of this pattern here:
http://mvccbl.com/Home/Examples[^]
Hope that helps!
Regards,
Mikhail
|
|
|
|

|
I have followed this to the letter, however it is giving me an error on CheckBoxListFor :
Compiler Error Message: CS0411: The type arguments for method 'MvcCheckBoxList_Extensions_Model.CheckBoxListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Linq.Expressions.Expression>>, System.Linq.Expressions.Expression>, System.Linq.Expressions.Expression>, System.Linq.Expressions.Expression>>, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Also, in your example above, you seem to switch between NewLicense and NewLicenseModel..
Now, I have:
public class NewLicenseViewModel
{
public NewLicenseModel NewLicense { get; set; }
public IEnumerable<LicensableFeatureModel> AvailableLicensableFeatures { get; set; }
}
public class NewLicenseModel
{
public string SomeProperty { get; set; }
public string[] LicensedFeatures { get; set; }
}
And finally in my view:
@model Licensing.Web.Models.NewLicenseViewModel
@Html.CheckBoxListFor(x=>x.,
x => x.AvailableLicensableFeatures,
x => x.ID,
x => x.Name,
x => x.NewLicense.LicensedFeatures)
Controller looks like:
[HttpPost]
public ActionResult Create(NewLicenseModel licenseRequest)
{
|
|
|
|

|
For your setup to work you need to change checkbox list call (add name property):
@Html.CheckBoxListFor(x => x.NewLicense.LicensedFeatures, x => x.AvailableLicensableFeatures,
x => x.ID,
x => x.Name,
x => x.NewLicense.LicensedFeatures)
Than change the name of the parameter for controller to newLicense:
[HttpPost]
public ActionResult Create(NewLicenseModel newLicense){
string[] selectedValues = newLicense.LicensedFeatures;
}
Let me explain how it works in more detail -
1) The name of checkboxlist selected is NewLicense.LicensedFeature, and that creates a set of checkboxes on html output looking something like this:
<input id="NewLicense.LicensedFeatures1" name="NewLicense.LicensedFeatures" type="checkbox" value="1" >
<input id="NewLicense.LicensedFeatures2" name="NewLicense.LicensedFeatures" type="checkbox" value="2" >
<input id="NewLicense.LicensedFeatures3" name="NewLicense.LicensedFeatures" type="checkbox" value="3" >
2) Then when you check some and post them back the default MVC convention matches first part of the name property NewLicense to the matching name of controller parameter, newLicense in our case. Name is not case sensitive, but it has to match exactly.
3) Next it will try to match an array of LicensedFeatures to a similar named property of class NewLicenseModel which is a string array of LicensedFeatures.
Try that, it should work now!
|
|
|
|

|
Sorry, there was an error in my previous post.
That's exactly how I have it in my view, however it's throwing an error there...
See this for example:
http://i.imgur.com/Ze6zC.png
|
|
|
|

|
Oh I see it now, sorry I missed this error at first:
The values selected has to be of the same type as source data values: IEnumerable<LicensableFeatureModel>
So your model and call to checkbox list should be this:
public class NewLicenseViewModel
{
public NewLicenseModel NewLicense { get; set; }
public IEnumerable<LicensableFeatureModel> AvailableLicensableFeatures { get; set; }
public IEnumerable<LicensableFeatureModel> SelectedLicensableFeatures { get; set; }
}
@Html.CheckBoxListFor(x => x.NewLicense.LicensedFeatures,
x => x.AvailableLicensableFeatures, x => x.ID,
x => x.Name,
x => x.SelectedLicensableFeatures)
Hope it will work now!
|
|
|
|
|

|
The ul is not present in the HtmlTag enumeration, is that correct?
|
|
|
|
|

|
Then please update the documentation for the latest version.
|
|
|
|

|
Yepp, I'll definitely update this article once latest beta version is finalized, since there will be few breaking changes.
|
|
|
|

|
public class ContentCategoryDO
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class ContentViewModel
{
public string Contents { get; set; }
public ICollection<Guid> CategoryIds { get; set; }
public ICollection<ContentCategoryDO> Categories { get; set; }
}
When I try this
@Html.CheckBoxListFor(m => m.CategoryIds,
m => m.Categories,
m => m.Id,
m => m.Name,
m => m.CategoryIds
)
the Id and Name are in red and when I mouse over the CheckBoxListFor I get the message "The type arguments for method 'MvcHtmlString MvcCheckBoxList_Extensions_Model.CheckBoxListFor |
|
|
|

|
Sorry if someone's already addressed this but I was wondering if CheckBoxListFor has a mechanism for refreshing the items in the list. Simple scenario is this: show user a list of available options as checkboxes using your CheckBoxListFor; separately, I also provide an 'Add' button in case a value the user needed to check is not already in the list; they save the new item (probably through an ajax post) then need to get handle on CheckBoxListFor to repopulate checkboxes so new item shows up. Thoughts?
|
|
|
|

|
For right now there is nothing like that built-in. This extension is a primarily server-side control with deep tie into the MVC ViewModel. At the current state it won't be practical to make it work in this way.
However, I see two ways to achieve what you need:
1) Easier way - it should be fairly simple to achieve that functionality by first posting new value to 'Add' via ajax call to a specific controller, than if this call returns successful result, reload the page via javascript, so that new value is added to the list.
2) A bit harder way - 'Add' new option to database via ajax call to a controller (like in #1) than, if that was successful, append checkbox html code to the list via jquery similar to that (so you won't need to reload the page):
$('.checkBoxList label:last').append('<input id="ID" type="checkbox" value="VALUE"><label for="ID">CHECKBOX_TEXT/label>');
Where .checkBoxList is a class of a <div> which wraps around the control.
|
|
|
|

|
Just pushed latest dev version 1.4.4.0 to github:
https://github.com/mikhail-tsennykh/MVC3-Html.CheckBoxList-custom-extension/tree/dev[^]
(do not use in production!)
Among other changes it now includes templating code by emillium[^], and implementation of boolean selector and dynamic tags proposed by cactussss[^].
Another major change is that I removed all .CheckBoxList overloads so only .CheckBoxListFor are used now. Also I introduced new internal class listConstructor which simplifies how overloads pass the data to ListBuilder.
Those are not all the changes I wanted for the new version, but they are the base ones.
Next big thing will be a cleanup and applying more single-responsibility to ListBuilder class, adding more examples to sample site, and some other stuff I haven't thought of yet))
|
|
|
|

|
Overall good release. Couple things though:
1. I am definatelly against this change: "I removed all .CheckBoxList overloads". There is a good reason these kind of overloads are included in MVC out of the box. Occasionally, POST model may differ from the GET model used to render a view. In such scenario TextBox(...) would be used instead of TextBoxFor(...).
2. It appears overload #13 has a bug (or I just don't understand how it should work).
Please try using following code:
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs,
x => x.AvailableCities,
x => x.Id,
x => x.Name,
x => Model.SelectedCities.Any(s => x.Id == s.Id),
new { @class = "MainHtmlAttrs" },
new HtmlListInfo(HtmlTag.vertical_columns, 1),
null,
null)
I could not find any items on the rendered page with class "MainHtmlAttrs".
Further testing showed that the last null is what prevents class "MainHtmlAttrs" to appear.
modified 25 Aug '12 - 22:10.
|
|
|
|

|
Great, thank you!
#1.
Well, here is my reasoning for removal of .CheckBoxList overloads, I removed them because they mostly had just duplicate code as a .CheckBoxListFor except for using string as name of the list, which I figured would be easy to customize just by adding another empty property to the model (e.g. public object MyCustomCheckboxListName { get; set; }), and with addition of singular (boolean) selector it would make the extension have 4 similar overloads for each level, which will be harder to maintain... Here is the example of what I mean:
@Html.CheckBoxListFor(x => x.CustomListName,
x => x.AvailableCities,
x => x.Id,
x => x.Name,
x => null)
Where CustomListName is this model property use just to generate name (name="CustomListName"):
public object CustomListName;
#2.
To make overload work do this:
@Html.CheckBoxListFor(model => model.PostedCities.CityIDs,
model => model.AvailableCities,
entity => entity.Id,
entity => entity.Name,
entity => Model.SelectedCities.Any(s => entity.Id == s.Id),
new { @class = "MainHtmlAttrs" },
new HtmlListInfo(HtmlTag.vertical_columns, 1),
null,
model => null)
You basically just add x => (model =>) in front of last null and it will render the tag, since it wants an expression.
Also if both last two values are null, you can use this instead:
@Html.CheckBoxListFor(model => model.PostedCities.CityIDs,
entity => entity.AvailableCities,
entity => entity.Id,
model => model.Name,
x => Model.SelectedCities.Any(s => x.Id == s.Id),
new HtmlListInfo(HtmlTag.vertical_columns, 1),
entity => new { @class = "MainHtmlAttrs" })
What do you think?
|
|
|
|

|
#1.
Your use of listConstructor does a good job of making sure no code would be duplicated. The only thing that would look like duplicate is the call to _listBuilder.CheckBoxList(...), but that's OK since it's a new overload.
I understand that maintenance is a hassle sometimes, but that should not get in a way of functionality of the extension. Having dummy properties on the model is unclean and inelegant code.
Having said that I propose placing all CheckBoxListFor overloads in a single file (example: CheckBoxListForOverloads.cs) and working only on these during development. When ready to release, just do these 4 steps:
------------------------------------------------------
1. copy all these extensions into a new file (example: CheckBoxListOverloads.cs)
2. modify their name from CheckBoxListFor to CheckBoxList.
3. rename Expression<Func<TModel, TProperty>> listNameExpr into string listName
4. change listName = listNameExpr.toProperty() to listName = listName
------------------------------------------------------
These 3 steps will take you 3 minutes and you only have to perform them when you are ready for a new release which takes care of maintenance issue.
I have to go to work now and will examine #2 when I come back.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Extends MVC HtmlHelper class so you can create POSTable checkbox list.
| Type | Article |
| Licence | CPOL |
| First Posted | 29 Nov 2011 |
| Views | 162,667 |
| Downloads | 6,122 |
| Bookmarked | 102 times |
|
|