13

I'd greatly appreciate if someone could advise on following: In my view I display the list of items:

@model PagedList.IPagedList<Items>
@using PagedList.Mvc; 
 @foreach (var item in Model)
          {//displaying data}

my pager looks like this:

@Html.PagedListPager(Model, page => Url.Action("Index", new { humanID = ViewBag.HumanID, page = page }),
                                                             new PagedListRenderOptions
                                                             {
                                                                        LinkToFirstPageFormat = "<<",
                                                                        LinkToPreviousPageFormat = "prev",
                                                                        LinkToNextPageFormat = "next",
                                                                        LinkToLastPageFormat = ">>",

                                                              })

The problem is that when I click on the next page it is returned blank, without my _Layout. I wouldn't like to reload _Layout all the time. Is there a way to use Ajax.ActionLink for pager? So that I could UpdateTargedId inside my partial view?

Dmitry Pavliv
  • 34,126
  • 12
  • 75
  • 77
Gyuzal R
  • 1,547
  • 7
  • 45
  • 92

3 Answers3

32

You cannot use Ajax.ActionLink but you could AJAXify the links. Put the pager in a <div>:

<div id="myPager">
    @Html.PagedListPager(
        Model, 
        page => Url.Action(
            "Index", 
            new { 
                humanID = ViewBag.HumanID, 
                page = page 
            }
        ),
        new PagedListRenderOptions
        {
            LinkToFirstPageFormat = "<<",
            LinkToPreviousPageFormat = "prev",
            LinkToNextPageFormat = "next",
            LinkToLastPageFormat = ">>",
        }
    )
</div>

and then AJAXify the links:

$(function() {
    $('#myPager').on('click', 'a', function() {
        $.ajax({
            url: this.href,
            type: 'GET',
            cache: false,
            success: function(result) {
                $('#some_grid_container').html(result);
            }
        });
        return false;
    });
});

Notice that in the success callback I've used $('#some_grid_container') which should be some wrapping div around your entire table.

Darin Dimitrov
  • 960,118
  • 257
  • 3,196
  • 2,876
  • 1
    Best solution i've ever seen! A bit changed to $('#myPager a').click(function () {}) and now it works! Thanks a lot! – Gyuzal R Sep 16 '13 at 07:59
  • 2
    Oops, my mistake. It should be `$('#myPager').on('click', 'a', function() { ... });` instead of `$('#myPager').on('a', 'click', function() { ... });`. Thanks for pointing that out. This allows for subscribing to the click event in a *lively* manner meaning that even if you update the page links in the DOM you don't need to re-register the click handler again. – Darin Dimitrov Sep 16 '13 at 08:57
  • @DarinDimitrov : There is a problem with this solution. you click on page 2, ok ? then page 2 is deactivated. but you click again on page 2. it shows results into the last results. is there any way for disabling deactivated page number? – Persian. Oct 25 '13 at 11:39
  • 1
    @DarinDimitrov : I add this code and it works correctly now : var lpage; $('#myPager').on('click', 'a', function () { var page = purl(this.href).param('page'); if (page == lpage) { return; } lpage = page; – Persian. Oct 25 '13 at 13:17
  • great nice solution for partial view – MSTdev Oct 31 '13 at 13:18
  • @Persian., i tested your solution to solv problem in DarinDimitrov code, and you have a problem. When you move page, will lose the partial and load all page – CesarMiguel Mar 03 '14 at 17:19
  • 1
    @Persian. i did `if (this.href == "") { return;}` to solv your problem – CesarMiguel Mar 03 '14 at 17:34
  • @DarinDimitrov thank you so much again your answers are always so helpful. – Enzero Jan 08 '15 at 07:59
  • Why do i use the entire layout using this code? it just shows my partial view after a few clicks on the pagelistpager.. the first few times it works perfectly, but then it starts to bug out.. – MMM Aug 21 '15 at 08:56
  • 1
    what if we want to **bookmark** example: page 2 , as you said [here](http://stackoverflow.com/a/20824965/2218697) in address bar query strings are not present on Ajax GET, is there any solution using ajax history [plugins](http://stackoverflow.com/questions/3242644/the-best-ajax-history-and-bookmark-plugin-currently-available)? – Shaiju T Feb 22 '16 at 09:51
  • Not working in asp.net core. Where is the controller parameters such as the page? – Just Fair Dec 09 '18 at 08:05
8

There is still a way to implement Ajax with PagedList.

@Html.PagedListPager((IPagedList)Model,
 page => Url.Action("Index", new { humanID= ViewBag.HumanID, page }), PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(PagedListRenderOptions.PageNumbersOnly,
        new AjaxOptions
        {
            InsertionMode = InsertionMode.Replace,
            HttpMethod = "Get",
            UpdateTargetId = "targetContainer"
        }))

This piece will make ajax request and replace the content with in "targetContainer". It gives you many more options in regards to Ajax call and the way you wish this to be displayed.

bummi
  • 26,435
  • 13
  • 58
  • 97
Utkarsh
  • 384
  • 3
  • 6
  • I want to implement pager as in your post, but response aren't replace content in targetContainer. What can cause this? Thanks – demo Feb 08 '16 at 14:54
  • PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing("targetID") was enough for my needs – Ken Mc Mar 22 '16 at 23:22
  • 2
    I've seen a lot of posts explaining how to use AjaxOptions to do stuff like this, but NONE of them let you know that you need jquery.unobtrusive-ajax.js in order for this to work. You can put all the Ajax options you want but if you don't have this library in your bundle nothing will work. – Barry Franklin Nov 29 '16 at 15:47
3

My project setup: MVC4, MvcPaging (PagedList), with Areas. This answer is geared towards that setup.

Short Answer:
While configuring your AjaxOptions for the pager, ensure you set your area (properly)

new AjaxOptions { UpdateTargetId = "grid-list" , OnBegin = "beginPaging", 
                  OnSuccess = "successPaging", OnFailure = "failurePaging"}
        , new { area = "Admin", controller = "MyController", action = "Index"}

Long Answer:
The PagedList sample shows how to pass to an area and do paging within an area, but they do not show a sample of how to use paging with a Partial View.

The sample project has the following code (taken from _AjaxEmployeeList.cshtml):

}, new AjaxOptions
            {
                UpdateTargetId = "grid-list",
                OnBegin = "beginPaging",
                OnSuccess = "successPaging",
                OnFailure = "failurePaging"
            }, 
    new { controller = "Home", action = "Index", 
        employee_name = ViewData["employee_name"] }))

The PagedList sample uses an inline table inside a foreach, so you do not have any problems/conflicts with this setup.

@using MvcPaging
@model IPagedList<MvcPagingDemo.Models.Employee>
<table class="table table-bordered table-hover">
        @foreach (var item in Model)
        { 
            <tr>
               <td>@item.ID</td>
            </tr>
        }    
</table>

While refactoring this table into a partial view (to encapsulate logic (and to deal with paging), I started to get a "The partial view '_MyPartialView' was not found or no view engine supports the searched locations"

@using MvcPaging
@using MyProject.Models
@model IPagedList<MyProject.Models.MyModel>
  foreach (var item in Model)
        {
        <div data-task-id="@item.MyModel_ID.ToString()">
            @Html.Partial("_Detail", item)
        </div>
        }

I went through a ration of changes attempting to force the area into the Html.Partial() call, including:
Modifying how routing is handled, which didn't work.
How to set a Default Route (To an Area) in MVC
Fully qualifying the path to the partial view, which did work but was ugly.
mvc3 - using partial views in a different area
The research into getting the partial views to load showed me how the MVC engine processes requests. This sent me back to modifying the Ajax Pager, to send the area with each request. I tried to use a similar syntax as the Html.ActionLink. (This didn't/doesn't work)

@Html.ActionLink("Admin", "Index", "Admin", new { area = "Admin" }, null)

That didn't work,so failing all else, I mirrored the pattern for setting the controller, which leads us to:

new AjaxOptions { UpdateTargetId = "grid-list" ,  OnBegin = "beginPaging", 
                  OnSuccess = "successPaging", OnFailure = "failurePaging"}
           , new { area = "Admin", controller = "MyController", action = "Index"}

My personal lesson from this: C# != Razor != Javascript. Each does things slightly differently and you have to be sure you know which language the line your writing is for.

Community
  • 1
  • 1
Lodlaiden
  • 162
  • 6