Draggable Sorting and Saving Changes using MVC and jQuery UI

By | May 15, 2012

We’ve been posting a lot of MVC and jQuery lately and I guess you have to get used to it for a couple of months more as this the technology that I am using currently in most of my projects. For today’s session I will be discussing on how to make a sortable list which you can drag and pass that sorted list information back to your server.


Not let’s make some assumptions.

Lets say you want a list to be sortable in your web project, usually Old school UI’s do it the Sharepoint way like this

or the old windows way like this

and I can’t blame developers who did this as this is the easy way to do it for a web UI, I myself made some sorting like this before. But now thanks to jQuery and jQuery UI things are much better and tasks like this just needs an element id and call the .sortable() method.


Now before we start lets dissect first what we need, and here it is

  1. A view which we call SortingOptions
  2. A view model to define the Sorting Options, we call the parent view model as UserPreferenceViewModel and the child view model which contains the details of each item on the list as UserPreferenceDetailViewModel
  3. A controller which contains two actions, InitializeModifyView which populates your view model and SaveUserPreferenceDetails which saves the ordering of the list

Lets start.

First here is how your View Model should look like for this example, I think the property names are self-explanatory.

public class UserPreferenceViewModel 
{
    public int Id { get; set; }
    public IList<UserPreferenceDetailViewModel> UserPreferenceDetails { get; set; }
}
public class UserPreferenceDetailViewModel 
{
    public int Id { get; set; }
    public string Description { get; set; }
    public bool IsEnabled { get; set; }
    public int ColumnOrder { get; set; }
}

Next is the View. There will be 3 main sections that I want to cover here, first is to import the jQuery and jQuery UI Scripts

<script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.ui.core.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.ui.widget.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.ui.mouse.js")" type="text/javascript"></script>   
<script src="@Url.Content("~/Scripts/jquery.ui.sortable.js")" type="text/javascript"></script>

You need all of these references for the sortable function to work, it’s the documented dependencies you will see in the jQuery UI site. If you don’t have the jQuery UI you can get it here, the downloads can be customized to what you need. You can also use NuGet but there is a catch, it will work but the jQuery dependency listed is between versions 1.4.4 and 1.6(as of this posting date)

which will automatically download the 1.4 if you have a different version of jQuery. And yes the jQuery UI will work in 1.7 thats what I am using.

Now let’s go to the UI elements, it’s a simple <ul> and <li>’s with id’s so we can refer to them easily. You will also notice that we will be looping to all the UserPreferenceDetails to show that on the <li>element. The span will show the image and there will be a checkbox if you want to enable/disable the list item. There will be also button for saving the users preference.

@model UserPreferenceViewModel
@using YourNamespace;
@{
    Layout = null;
}

<div id="modify-view-command">
    <p class="message information">Drag the columns up and down according to the order you want, you can choose the items you want to enable/disable by ticking the check box</p>
    <button id="save-view-preferences" class="t-button">
        Save Changes</button>
</div>

<div id="modify-view-elements">
    <ul id="sortable">
        @foreach (UserPreferenceDetailViewModel m in Model.UserPreferenceDetails)
        {
            <li><span id="sort-updown"></span>
                @Html.CheckBox("chkEnabled" + m.Id, m.IsEnabled, new { @class = "EnabledFlag" })
                @m.Description
                @Html.Hidden("hdnId-" + m.Id, m.Id, new { @class = "ItemId" })
            </li>
        }
    </ul>
</div>

Finally the jQuery that makes everything happen, here you now refer to the sortable element which is our <li>,this is what makes it happen when you apply a sortable() method on it. You will also notice that we are passing an array to our Action / Controller and you need to make sure the names are exactly the same as your View Model in this case the UserPreferenceDetail, MVC will automatically then map this so you don’t need to interpret the data, all you need is to pass it as a JSON String. Also on that array you will pass the index which is the sorted index value of the list, this will take care of your Sorting Order value.

<script type="text/javascript">

$(function () {
    $("#sortable").sortable();
    $("#sortable").disableSelection();
    $("#save-view-preferences").click(saveUserPreferenceDetails);
});

function saveUserPreferenceDetails() {
    var userViewPreferenceDetails = new Array();
    $("#sortable li").each(function (index) {
        var userPreferenceItem = new Object();
        userPreferenceItem.Id = $(this).find($(".ItemId")).val();
        userPreferenceItem.IsEnabled = $(this).find($(".EnabledFlag")).attr("checked") == "checked" ? true : false;
        userPreferenceItem.ColumnOrder = index;
        userPreferenceDetails.push(userPreferenceItem);
    });
    $.ajax({
        type: 'POST',
        url: '/YourActionName/SaveUserViewPreferenceDetails',
        data: JSON.stringify(userPreferenceDetails),
        dataType: 'json',
        contentType: 'application/json; charset=utf-8',
        success: function () {
            window.location.replace("http://whereyouwantogoafter.com");
        }
    });
}

</script>

Now for the Actions. InitializeModifyView is a simple as popualting the view model and SaveUserPreferenceDetails takes care of the saving. And if you notice it accepts a list of UserPreferenceDetailViewModel and thats the one that we created as an array and stringify from our jQuery code.

[HttpPost]
public JsonResult InitializeModifyView()
{
    var viewModel = yourQuery.PopulateViewModel();

    return Json(new { viewHtml = RenderRazorViewToString("SortingOptions", viewModel) }); 
}

public virtual void SaveUserViewPreferenceDetails(List<UserPreferenceDetailViewModel> savedItems)
{
    foreach (var item in savedItems)
    {
        yourTasks.SaveUserPreferenceDetail(item);
    }
}

Easy enough? well imagine life without jquery!


One thought on “Draggable Sorting and Saving Changes using MVC and jQuery UI

  1. Nats

    love it, is it possible to target a different element, like a get from server in the drop handler.

    Reply

Leave a Reply