CheckBox Helper

Looks like everyday challenges are keeping this blog active… :). Here again, is a new requirement which led to workarounds from the suggestions/solution proposed my many on the net.

The need
Accepting courses held on various days of the week and storing the same in a single field in database table, of course, as a string. And later allowing the user to edit the stored values and saving the new selection back to the table.

Day of the week

While binding, we bind only to one field in the model, but need to display multiple checkboxes. A string value (stored as ‘0101010’, for the above selection) where every digit represents the selection value of that day, 0 for false and 1 for true. Thankfully, there are only seven days in a week… :).

The solution
Could have been a ListBox or CheckBoxList type, but that would show the options in a box and top down. For days of the week, a horizontal selection makes the interface more appealing and friendly.

So it had to be a HTML helper extension. A class and function to be created to for this, as below,

namespace Project1.Helpers
{
public static class CheckBoxHelper
{
public static MvcHtmlString DoWCheckBox(this HtmlHelper html, Expression<Func> expression)
{

This HtmlHelper extension is invoked in the view (Edit.cshtml) as below,

@model Project1.Models.COURSE_MST
@using Project1.Helpers;

@Html.DoWCheckBox(model => model.Held_On)

The extension function parameter expression would hold the ‘model.Held_On’, and parameter html would have the values, i.e, ‘0101010’ in the above case. Only the Edit part is shown here, something similar needs to be done for Create of the controller.

public static MvcHtmlString DoWCheckBox(this HtmlHelper html, Expression<Func> expression)
{
// get the name of the property, split ‘model.Held_On’
string[] propertyName = expression.Body.ToString().Split(‘.’);
string[] wod = {“Sun”, “Mon”, “Tue”, “Wed”, “Thu”, “Fri”, “Sat”};

// get the value of the property
Func compile = expression.Compile();
string strValue = compile(html.ViewData.Model);
var sb = new StringBuilder();

for (int i = 0; i < strValue.Length; i++)
{
TagBuilder checkbox = new TagBuilder(“input”);

checkbox.MergeAttribute(“id”, propertyName[1]);
checkbox.MergeAttribute(“name”, propertyName[1]);
checkbox.MergeAttribute(“type”, “checkbox”);
checkbox.MergeAttribute(“value”, Convert.ToString(i));
if (strValue.Substring(i,1) == “1″)
checkbox.MergeAttribute(“checked”, “checked”);

TagBuilder label = new TagBuilder(“label”);
label.MergeAttribute(“for”, wod[i]);
label.SetInnerText(wod[i]);

sb.Append(checkbox);
sb.Append(label);
}
return MvcHtmlString.Create(sb.ToString());
}

As you would have noticed, we are not using hidden type html tags to store the value, but storing integer variable ‘i’ value (checkbox.MergeAttribute(“value”, Convert.ToString(i))).

This would generate the required list of selected days of week and display with the same id and name, thus allowing us to get the new selection under one variable. To capture the new selection we would modify the Edit (post) as below,

[HttpPost]
public ActionResult Edit(COURSE_MST course_mst, int[] Held_On)
{

Watch window

As this checkbox value stores an integer, a int array is the additional parameter to the function (note the variable values in the watch window). The array would contain the values only where the checkboxes have been selected, values for the non-selected checkboxes is not sent to the controller.

The values in this example contain ’1,6′ representing Mon and Sat, which translates to ’0100001′…

Take charge.

Posted in MVC3, Solutions, UI | Tagged , , , , | Leave a comment

ListBoxFor – Displaying selection in Edit page

Does sound very simple, but it took a while to get it working in the desired manner. There weren’t any solutions on single place, read and tried multiple methods to get the right output.

Found this link which comes close to my solution, customised it to suit my need.

The need

A vendor master, were one of the fields stores the business(es) the vendor is in and they could be either one or many. List of businesses was stored in a separate table, constants. To allow the user to select multiple businesses, a list box control was to be used.

The application was to allow the user to change the vendor business, through edit page. That would mean, to display the stored selection in the edit page, and storing new selection to database.

Solution

In the Controller class for Edit function (Get), we would store the list of values with ids into a ViewBag variable. As below code represents,

// GET: /Vendor_Table/Edit/5
public ActionResult Edit(int id)
{
ViewBag.Item_Value = from a in db.CONSTANT_TABLE
                             where a.ID == “3″
                      select new { Constant_ID = a.Constant _ID, Value = a.Value };

The variable Item_Value would store just two column values, ID and Value.

In the View, Edit.cshtml, the code would look like this,

@Html.ListBoxFor(model => model.Vendor_Business, new MultiSelectList(ViewBag.Item_Value, ” Constant_ID”, “Value”))

The model.Vendor_Business which contains the stored value (as comma separated, like 1,3,5) will be the selected values and ViewBag.Item_Value would display the entire list of business available in the constant table.

This would work just fine, but the catch is, during edit if the user changes the selection and submits the form. The controller would receive only the first selected value and not all the selection. That is because the Vendor_Business will not bind to the model, but will be available as variable.

To get all selected values, we need to modify the Edit function (post), to accept additional parameter of array type.

[HttpPost]
public ActionResult Edit(VENDOR_TABLE vendor_table, int[] Vendor_Business)
{

The Vendor_Business variable of int[] type would contain the selected IDs, again the type necessarily need not of int, any type but an array.

Before having worked on this, I was using the FormCollection to get all the values and later separated them.. phew!!. I am happy this worked for me.

Take charge.

Posted in MVC3, Solutions | Tagged , , , | Leave a comment

Dynamic rows with cascading drop down list

Though very new to the jquery, a lot of reading and experimenting with the code has given me the desired output. I am sure there would be better ways to implement the same, and I look forward to your inputs to improve this.

Refer to this question and the solution on JSFiddle, by Robert Koritnik, I was able to work on the code to get dynamic rows with cascading drop down lists , also refer to tmpl (jquery plugin). Here is what I did.

The Need

In a typical stores and stores transaction scenario, where the items are grouped based on the categories like Electrical, Plumbing, Housekeeping, etc. Under these respective categories lie the items like Bulbs, Mops, Pipes, etc. To store these two models were created in MVC3, one for Stores Master and other for Stores Transactions,

public partial class STORE_MST

{
public virtual int Item_ID{ get; set; }
public virtual string Item_Name{ get; set; }
public virtual short Item_Category{ get; set; }
}

The Item_Category would be fetched from a table storing all the constant values. Transaction details were stored as below,

public partial class STORE_TRAN
{
public virtual int Tran_ID{ get; set; }
public virtual int Item_ID{ get; set; }
public virtual int Qty{ get; set; }
}

(Above models are only for reference)

Output Needed

Button “Add Row” would dynamically append addition rows of controls to the list and button “Remove” would delete the respective row.

Solution

Two JSonResult type functions created in the controller, to fetch the records from the database, one function to get the list of categories and another to get items based on the selected category.

[AcceptVerbs(HttpVerbs.Get)]
public JsonResult LoadCategory()
{
//Code to fetch the item categories, using SelectListItem()
return Json(<SelectData>, JsonRequestBehavior.AllowGet);
}

Likewise, the same for getting the items based on category,

[AcceptVerbs(HttpVerbs.Get)]
public JsonResult LoadItems(string id)
{
//Code to fetch the item names, using SelectListItem()
return Json(<SelectData>, JsonRequestBehavior.AllowGet);
}

In the cshtml code, within the <Form> in the markup

<input type=”button” id=”addItem” value=”Add Row” />
<div id=”container”></div>

Script below to create the list of controls to be displayed, a variable outside the function to initialise and increment the “count”.

<script id=”template” type=”text/x-jquery-tmpl”>

<div>
<select id=”Item_${count}” name=”Item_Category[${count}]” onchange=”javascript:LoadItem($(this))”><option value=””>Select a Category </option></select>
<select id=”Item_${count}_Name” name=”Item_Name[${count}]“><option value=””>Select a Item</option></select>
<input type=”text” name=”Quantity[${count}]”  id=”Qty_${count}”/>
<select id=”Adj_${count}” name=”ddlAdjEntryType[${count}]“><option value=”0″>Yes </option><option value=”1″>No</option></select>
<input type=”button” onclick=”RemoveRow(this)” value=”Remove” />
</div>
</script>

The LoadItem function is invoked on change of category,

// Load the items based on the category selected

function LoadItem(id) {
var idCat = $(id).val();
var requrl = “/STORE_TRN/LoadItems/” + id.val();
$.ajax({ type: “get”, dataType: ‘json’, cashe: false, url: requrl,
success: function (data) {
var str = “#” + $(id).attr(“id”) + “_Name”;
$(str).empty();
$.each(data, function (index, value) {
var optStr = “<option value=’” + value.Value + “‘>” + value.Text + “</option>”;
$(str).append(optStr);
})
},
error: function (failure) { alert(failure.responseText); }
});
}

The LoadCategory function is called on load of the control

// Load the category

function LoadCategory(id) {
var requrl = “/STORE_TRN/LoadCategory/”;
var item_id = id.isPrototypeOf();
$.ajax({ type: “get”, dataType: ‘json’, cashe: false, url: requrl,
success: function (data) {
var str = “#” + $(id).attr(“id”);
$.each(data, function (index, value) {
var optStr = “<option value=’” + value.Value + “‘>” + value.Text + “</option>”;
$(str).append(optStr);
})
},
error: function (failure) { alert(failure.responseText); }
});
}

On click of the “Add Row” button the “#addItem” function is called,

$(document).ready(function () {
var counter = 1;
$(“#addItem”).click(function (evt) {
evt.preventDefault();
$(“#template”).tmpl({ count: counter }).appendTo(“#container”);
LoadCategory($(“#Item_” + counter));
counter++;
});
});

Of course, the code to remove the row can be implemented by removing the <div> nodes.

If you have noticed, all the ids and names of the controls are assigned dynamically, in order to bind parent DDL with the child DDL.

Take charge.

Posted in Uncategorized | Tagged , , , , , | Leave a comment