views:

52

answers:

3

On my webpage I am displaying a table of data and I want to give the user the ability to sort that data by using a dropdownlist (e.g. By FirstName, By LastName, By State etc...).

I would like to use Ajax to load the sorted data into the data table without a page refresh. I'd also like to use javascript in an unobtrusive way so that the user can still sort if javascript is disabled. This is my first time at trying this approach.

I have been following along with some code in 'ASP.NET MVC In Action' as my template. So far I have:

Webpage

<% using (Html.BeginForm("SortCourseData", "Summary", FormMethod.Post, new { id = "summarysort"})) %>
<% { %>
<div id="sort"><%=Html.DropDownList("SortSelection", Model.sortList, new { onchange="this.form.submit();" })%> </div>         
<% } %>

Rendered HTML

<form action="/Summary/SortCourseData" id="summarysort" method="post">
    <div id="sort"><select id="SortSelection" name="SortSelection" onchange="this.form.submit();"><option>Incomplete</option>
    <option>By first name</option>
    <option>By last name</option>
    <option>By state</option>
    </select> </div>         
</form>  

Jquery

$('form#summarysort').submit(function(event) {
    event.preventDefault();
    var sortKey = $("#SortSelection").val();
    hijack(this, updateList, sortKey, "html")
});

function hijack(form, callback, sortKey, format) {
    $.ajax({
        url: '/Summary/SortCourseData',
        type: "POST",
        data: 'SortSelection=sortKey',
        dataType: format,
        success: callback
    });
}

function updateList(result) {
    $('div#datadisplayarea').html(result);
}

Controller

public ActionResult SortCourseData(string SortSelection)
    {
        SummaryViewModel m = new SummaryViewModel();
        SummaryViewData modelData = m.GetViewModelData(SortSelection);

        if (Request.IsAjaxRequest())
            return PartialView("SummaryCourseList", modelData);

        return View("Index", modelData);
    }

The issue that I am having is that when I select a sort method in the dropdownlist the submit event in my jquery does not capture the event. If I put a simple alert(); in the code block I do not get an alert which suggests that it isn't hooking into the form submit event.

How can I successfully hijack the form submit event so that I can use ajax to update my course table? Any guidance would be appreciated...

+1  A: 

Assuming a select box similar to:

<form action="" method="get">
<label for="sortBy">Sort by:</label>
<select id="sortBy" name="sortBy">
    <option value="0">id</option>
    <option value="1">First name</option>
    <option value="2">Surname</option>
    <option value="3">Website</option>
</select>
<input type="submit" value="Sort table" />
</form>

...and a table similar to the following:

<table id="sorting">
    <thead>
        <tr>
            <th>numerical Id</th>
            <th>first name</th>
            <th>surname</th>
            <th>website</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>Mike</td>
            <td>Masnick</td>
            <td>techdirt.com/index.php</td>
        </tr>
        <tr>
            <td>2</td>
            <td>Randall</td>
            <td>Munroe</td>
            <td>xkcd.com</td>
        </tr>
        <tr>
            <td>3</td>
            <td>Jerry</td>
            <td>Holkins</td>
            <td>www.penny-arcade.com</td>
        </tr>
        <tr>
            <td>4</td>
            <td>Mike</td>
            <td>Krahulik</td>
            <td>www.penny-arcade.com</td>
        </tr>
    </tbody>
</table>

Rather than using Ajax (and hitting the network every time your user wants to re-sort the table that's already loaded) I'd suggest, instead, using the jQuery plug-in "tablesorter" (or any of the equivalents) , and calling it like so

$(document).ready(
 function(){

    // hides the submit button (to avoid having to hijack the submit event)
    $('input:submit').remove();

    // sorts the table on load.
    $('#sorting').tablesorter();

    $('#sortBy').change(
        function() {
            // call the tablesorter plugin 
            var sortedBy = parseInt($('#sortBy').val());
               $("#sorting").tablesorter({
            // sort on the first column and third column, order asc 
               sortList: [[sortedBy,0]] 
         }); 
    })
 }
);

Demo over at: JS Bin.

David Thomas
Thanks for the heads up on 'tablesorter'. Agree it is more efficient and I will look into that. Issue remains that this won't work if user does not have javascript enabled so will need to perform a sort on the server side in these instances...
Remnant
@Remnant, agreed; I just tend to forget that some disable JS, and when I do remember I tend to leave a `noscript` suggesting they might want to turn it on...I'm a bad man. And, apparently, a hypocritical advocate of graceful degradation. **cough**
David Thomas
@Remnant, I just re-read your comment and...if the user doesn't have **JS enabled** then the request will go to the server automatically, as defined by the `action` attribute of the form, so all would be well. Tablesorter wouldn't (be able to) interfere. That said, I've edited the answer to remove the `submit` button from the form so the user, with JS enabled, isn't able to submit the form (you could use `$('form').submit(function(){return false;});` instead, though. Those without js still the submit button to re-sort.
David Thomas
A: 

The submit event only fires when the user submits the form, it won't if JavaScript does it.

You'll need to modify the onchange handler.

David Dorward
@David - Can I clarify my understanding with your help please? You are saying that onchange="this.form.submit(); won't cause the form submit event to fire and this is why I can't capture the form event in my jQuery code. On that basis, if I want to use javascript unobtrusively (i.e. allow user to use dropdown to update data table even if they have js turned off) then I would need to actually display a submit button for them to click as my current (onchange) method relies on them having js enabled. Is this correct?
Remnant
Yes, that is why it isn't firing and why you can't capture it with the jQuery code. Yes, you would need a submit button to let people submit forms without JS.
David Dorward
+1  A: 

try

$("#SortSelection").change(function(){
     $('form#summarysort').submit();
});
D.J

related questions