Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / jQuery

Draggable Sorting and Saving Changes using MVC and jQuery UI

5.00/5 (2 votes)
7 Oct 2013CPOL3 min read 23.1K  
How to make a sortable list which you can drag and pass that sorted list information back to your server.

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.

C#
public class UserPreferenceViewModel 
{
    public int Id { get; set; }
    public IList<UserPreferenceDetailViewModel> UserPreferenceDetails { get; set; }
}
C#
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

C#
<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.

C#
@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.

C#
<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 populating 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.

C#
[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!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)