sgjsakura / AspNetCore

ASP.NET Core Extension Library
Apache License 2.0
162 stars 26 forks source link

Ajax pager help #13

Closed dthunder746 closed 8 years ago

dthunder746 commented 8 years ago

Hey mate, having a bit of an issue using the ajax pagination. I am trying to do simple table pagination, and I've got it working using direct links, but ajax would be preferable. I've used the library suggested in the demo and enabled ajax navigation on the pager. If I leave it at that, obviously clicking the pagination buttons results in nothing happening. I then read issue https://github.com/sgjsakura/AspNetCore/issues/8 and experimented with what you suggested there. Upon adding the method and update attributes it kind of worked, however it inserts an updated version of the entire page body it into the specified div. How do I get it to only update the table? I don't have much experience with ajax, so i'm sure this is relatively simple to fix, so a prod in the right direction would be appreciated!

this is my current pager code:

<pager source="Model.Result" item-default-link='PagerItemLinkGenerators.QueryName("resultpage")' setting-link-attr-data-ajax="true" setting-link-attr-data-ajax-method="GET" setting-link-attr-data-ajax-load="#results" />

And the table in my view is something like this:

<table id="results" class="table">
            <tr>
                <th>
                    headers
                </th>                
            </tr>
            @foreach (var item in Model.Result)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.ResultExample)
                    </td>
                </tr>
            }
</table>
sgjsakura commented 8 years ago

@dthunder746 Hi, thank you for your feedback. According to your question, the problem seems to be caused by the AJAX feature itself, not the pager.

Basically, AJAX is just send a HTTP request in background channel and get the response from the server. The AJAX request does not have much differences compared with regular user generated requests. Thus, If you are simply raises a request to a controller action and this action returns a view, the standard MVC processing pipeline will always do all necessary work like inserting layouts and sections, and then the complete page will be sent. The ajax-load directive just insert the response HTML into your container, so you may see chaos after navigation.

To use a most common and simple solution to this problem, you may change your code as bellow:

  1. make a special action for your your AJAX request, and design its view as it only contains the partial content which should be updated
  2. use return PartialView instead of return View, to supress the default layout handling when generation the response HTML

Hope it helps, and best wishes :-)

dthunder746 commented 8 years ago

Hey, thanks for the reply I appreciate the help.

So I have modified my action to return a PartialView to the GET request. Inspecting the response using the network tab in chrome dev tools, I can see partial view with the requested data is successfully sent back by the server, but it is now not being inserted into the #results table. I guess I'm still missing something.

Any tips?

The part of the action that returns the partial view (a bit hacky, but it works)

if (Request.Headers["X-Requested-With"] == "XMLHttpRequest")
      return PartialView("pagerPartial",viewModel);
else
      return View(viewModel);

The section of the view that contains the pager:

@Html.Partial("pagerPartial")
<div class="text-center">
     <pager source="Model.Result" item-default-link='PagerItemLinkGenerators.QueryName("resultpage")' setting-link-attr-data-ajax="true" setting-link-attr-data-ajax-method="GET" setting-link-attr-data-ajax-load="#results" />
</div>

The partial view:

<table id="results" class="table">
            <tr>
                <th>
                    headers
                </th>                
            </tr>
            @foreach (var item in Model.Result)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.ResultExample)
                    </td>
                </tr>
            }
</table>
sgjsakura commented 8 years ago

@dthunder746 Hi, according to my knowledge, the Microsoft Unobtrusive AJAX library uses data-ajax-update to control the insert location.

Hope it helps and best wishes :-)

dthunder746 commented 8 years ago

Awesome, thanks. After changing that and moving the pager inside the partial view, everything is working perfectly.

I noticed that a copy of &X-Requested-With=XMLHttpRequest was being appended to the href links in the pager on each ajax call, resulting in something like this after a few ajax calls:

~/controller/action/id?querystring=blah&X-Requested-With=XMLHttpRequest&X-Requested-With=XMLHttpRequest&X-Requested-With=XMLHttpRequest&X-Requested-With=XMLHttpRequest&X-Requested-With=XMLHttpRequest&X-Requested-With=XMLHttpRequest&X-Requested-With=XMLHttpRequest&X-Requested-With=XMLHttpRequest&X-Requested-With=XMLHttpRequest&_=12345678910

I guess this could be a problem if the user paginates enough, so I wrote a small jQuery function to remove these from the links after the ajax request is complete.

Thanks for the help mate, you're a legend.

sgjsakura commented 8 years ago

HI, it seems your problem is caused by http request handling. Your application will display the X-Requested-With query argument in the request url. Usually if you create a request using GET method, this argument will occur in AJAX requests.

Anyway, please make a double check for your code and it seems your original problem has been solved. I'm closing this issue and please feel free to reopen it if you have any new question :-)

fityanaula commented 7 years ago

@sgjsakura could you please provide me example how to use data-ajax-update ?

sgjsakura commented 7 years ago

@fityanaula hi, could you provide more information about your problem? Thank you.