Adding Ajax.ActionLink to DataTable column while using server-side processing?

▼魔方 西西 提交于 2019-12-13 06:13:06

问题


Alright, so I was unable to find any posts with people trying to do this.

I have an MVC4 razor view which contains a jQuery DataTable with a list of Vendor data. In the 1st column I have added 3 buttons: info/edit/delete, which open a partial view in a hidden div to the right of the table. I can do a foreach to loop through the model and write the table rows with Ajax Actionlinks and data columns for each item; this all works fine.

My issue came about when I decided to use server-side processing with DataTables because the list contains thousands of rows and the initial page load was very slow. I have server-side processing working fine, but I do not know how to go about getting the Ajax ActionLinks back into the 1st column.

For reference, I followed this article to get server-side processing set up with filtering, sorting, and paging and this all works fine.

I used mRender to add the buttons in anchor tags, but they do not work. In glimpse I can see my Ajax request returning a 404. The links render and when I hover on them the URL looks good, but glimpse is telling me:

Ajax GET 404 - Not Found - http://localhost/Vendor/Details/1?X-Requested-With=XMLHttpRequest

Here is my HTML and code which initializes the DataTable:

<div id="ListContent">
<table id="VendorList">
    <thead>
        <tr>
            <th></th>
            <th>Vendor Name</th>
            <th>Vendor District</th>
        </tr>
    </thead>
    <tbody>
        @* DataTables renders the data here *@
    </tbody>
</table>
</div>

<div id="DetailContentWrapper" class="collapsed">
    <div class="closeLink"></div>
    <div id="DetailContent">
        @* info/edit/delete partial views should load here *@
    </div>
</div>

<script>
$(document).ready(function () {
    $('#VendorList').dataTable({
        "bServerSide": true,
        "sAjaxSource": '@Url.Action("AjaxHandler")',
        "bProcessing": true,
        "bJQueryUI": true,
        "bAutoWidth": false,
        "sPaginationType": "full_numbers",
        "aoColumns": [
                        {
                            "mData": "VendorId", "bSearchable": false, "sWidth": "90px",
                            "mRender": function( data, type, full) 
                             { 
                                return '<a class="detailsButton" title="Details" href="/Vendor/Details/' + data + '" data-ajax-update="#DetailContent" data-ajax-mode="replace" data-ajax-method="GET" data-ajax-loading="#progress" data-ajax-begin="ExpandRightColumn" data-ajax="true"> </a> '
                                     + '<a class="editButton" title="Edit" href="/Vendor/Edit/' + data + '" data-ajax-update="#DetailContent" data-ajax-mode="replace" data-ajax-method="GET" data-ajax-loading="#progress" data-ajax-begin="ExpandRightColumn" data-ajax="true"> </a> '
                                     + '<a class="deleteButton" title="Delete" href="/Vendor/Delete/' + data + '" data-ajax-update="#DetailContent" data-ajax-mode="replace" data-ajax-method="GET" data-ajax-loading="#progress" data-ajax-begin="ExpandRightColumn" data-ajax="true"> </a> ';

                             }
                        },
                        { "mData": "VendorName" },
                        { "mData": "VendorDistrict" }
                    ]
        });
    });
</script>

The Ajax ActionLink I'm trying to reproduce looks like this:

@Ajax.ActionLink(" ", "Details", new { id = item.VendorId }, new AjaxOptions()
                                       {
                                           UpdateTargetId = "DetailContent",
                                           InsertionMode = InsertionMode.Replace,
                                           HttpMethod = "GET",
                                           LoadingElementId = "progress",
                                           OnBegin = "ExpandRightColumn"
                                       }, new { @class = "detailsButton", title="Details" })

The resulting HTML from the above ActionLink is this:

<a class="detailsButton" title="Details" href="/VendorMap/Details/1" data-ajax-update="#DetailContent" data-ajax-mode="replace" data-ajax-method="GET" data-ajax-loading="#progress" data-ajax-begin="ExpandRightColumn" data-ajax="true"> </a>

which is why that is what I'm using in mRender, but even though the resulting HTML is identical, the non-ajax link in mRender is not wired the same with MVC, and is therefore throwing the 404.

I even tried to pass to mRender:

return '@@Ajax.ActionLink(" ", "Details", new { id = ' + data + ' }, new AjaxOptions() { UpdateTargetId = "DetailContent", InsertionMode = InsertionMode.Replace, HttpMethod = "GET", LoadingElementId = "progress", OnBegin = "ExpandRightColumn" }, new { @@class = "detailsButton", title="Details" })';

but, as expected, it simply displayed that chunk as text in the first column.

Basically, I need to somehow wire my anchor tag to act like an Ajax Actionlink. Sorry if I haven't been clear, let me know if there is any more information I can provide.


I've made some progress, but am stuck again. I'm pretty sure it's impossible to render an Ajax Actionlink using jQuery, but what I can do is call an action method and render the resulting partial view. I have updated my mRender value to:

"mRender": function( data, type, full) 
                             { 
                                return '<a class="detailsButton" title="Details" id="details' + data + '" onClick="showDetails(' + data + ');"> </a>'
                                     + '<a class="editButton" title="Edit" id="edit' + data + '" onClick="showEdit(' + data + ');"> </a>'
                                     + '<a class="deleteButton" title="Delete" id="delete' + data + '" onClick="showDelete(' + data + ');"> </a>';
                             }

Then I have implemented the following functions:

function showDetails(id) {
    ExpandRightColumn()
    $.get('@@Url.Action("Details", "Vendor", new { id = "' + id + '"} )', function (data) {
        $('#DetailContent').html(data);
    });
}
function showEdit(id) {
    ExpandRightColumn()
    $.get('@@Url.Action("Edit", "Vendor", new { id = "' + id + '"} )', function (data) {
        $('#DetailContent').html(data);
    });
}
function showDelete(id) {
    ExpandRightColumn()
    $.get('@@Url.Action("Delete", "Vendor", new { id = "' + id + '"} )', function (data) {
        $('#DetailContent').html(data);
    });
}

ExpandRightColumn() simply displays the DetailContent div, where the resulting partial view should be rendered. The $.get(Url.Action should go to the Vendor controller, call the Details/Edit/Delete action method, and return the partial view rendered as html. It should then be pasted into the DetailContent div. Here is the source.

I have tested the Url.Action and it is returning the correct URLs. When I browse to the URLs I get the correct partial view. However, when I try to do the $.get on that URL, the server is returning a 404. Any ideas?


回答1:


I got it working. Apparently the Url.Action helper was returning a bad URL. When I just hardcoded the URL, everything worked.

I now have a DataTable which uses server-side processing with 3 buttons in the 1st column which load details/edit/delete partial views into a hidden div on the right.

If anyone wants to see the full code, let me know.




回答2:


if you put your javascript in *.js file, the solutions don't work. if you want to create a bundle, the solutions don't work too.

so, you can use this approach :

HTML

<table id="VendorList" 
data-ajax-url-details="@Url.Action("Details", "Vendor")"
data-ajax-url-edit="@Url.Action("Edit", "Vendor")"
data-ajax-url-delete="@Url.Action("Delete", "Vendor")">

Js

//for access to data :
$('#VendorList').data('url-details');

and you can do what you want for completing your own url and add the right id.



来源:https://stackoverflow.com/questions/18091699/adding-ajax-actionlink-to-datatable-column-while-using-server-side-processing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!