boost boost - 3 months ago 6
jQuery Question

After AJAX post and rebinding jQuery events, jQuery no longer works

I am attempting to build a pagination system for ASP.NET MVC; with partial views for a search form, the table that displays the data, and the pagination. I have it all laid out and it kinda works. I am not very good with jQuery, so I am really not sure where I am going wrong with this...

When I post using AJAX, the pagination stops working after updating the UI. I rebind my jQuery events using a function called

bindAllEvents()
, but it doesn't seem to actually rebind my events. My model is updated after the first call, and the second attempt to move to the next page using the "next"
>
link calls my controller action method, but nothing changes in the UI.

The jQuery:

$(document).ready(function() {
bindAllEvents();
});

function pageEvent() {
this.goToPage = function() {
// Not yet implemented
return false;
}
}

function nextEvent(nextPage) {
this.nextPage = function() {

var url = '@Url.Action("Manage")'
var data = @Html.Raw(Json.Encode(Model.Data));
var categories = @Html.Raw(Json.Encode(Model.Categories));
var _page = @ (Model.pager.CurrentPage + 1);

var _model = {
Data: data,
Categories: categories,
};

$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: url,
data: JSON.stringify({
model: _model,
page: _page
}),
success: function(result) {
//console.log("Success " + result);
$('div[id="pagination"]').html($(result).find('div[id="pagination"]'));
$('div[id="full-table"]').html($(result).find('div[id="full-table"]'));
$('div[id="search-form"]').html($(result).find('div[id="search-form"]'));
bindAllEvents();
},
error: function(result) {
console.log("Error: " + result.responseText);
}
});
}
}

function bindAllEvents() {
$('#date-boxes').slideUp(1);

// Have also tried $('body').on('click', '#next', ...) with no success
$('div[id="pagination"]').on('click', '#next', function(e) {
e.preventDefault();
var onNextClickEvent = new nextEvent();
onNextClickEvent.nextPage(@(Model.pager.CurrentPage + 1));
});

$("a[name='page-number']").on("click", function(e) {
e.preventDefault();
var onPageClick = new pageEvent();
onPageClickEvent.goToPage($(this).attr('id'));
});
}


And the HTML for the partial view for the pagination is the following

@if (Model.EndPage > 1)
{
<div style="color:#337AB7; padding-bottom: 0px;" id="page-counter">Page @Model.CurrentPage of @Model.TotalPages</div>
<ul class="pagination">
@if (Model.CurrentPage > 1)
{
<li>
@Html.ActionLink("<<", "Manage", null, new { id = "first" })
</li>
<li>
@Html.ActionLink("<", "Manage", null, new { id = "prev" })
</li>
}
@for (var _page = Model.StartPage; _page < Model.EndPage + 1; _page++)
{
<li class="@(_page == Model.CurrentPage ? "active" : "")">
@Html.ActionLink(_page.ToString(), "Manage", null, new { name = "page-number", id = _page })
</li>
}
@if (Model.CurrentPage < Model.TotalPages)
{
<li>
@Html.ActionLink(">", "Manage", "Announcements", null, new { id = "next" })
</li>
<li>
@Html.ActionLink(">>", "Manage", null, new { id = "last" })
</li>
}
</ul>
}


I will include the view with the partial views just for completeness, but I don't think it is too required.

<div id="search-form">
@{ Html.RenderPartial("_SearchForm", Model.Categories); }
</div>
<hr />
@if (Model.Data.Count == 0)
{
<h2>No existing announcements.</h2>
}
else
{
<div class="form-group" id="full-table">
@{ Html.RenderPartial("_Manage-AncmtListing", Model.Data); }
</div>
<br />
<div id="pagination">
@{ Html.RenderPartial("_Pager", Model.pager); }
</div>
}


Before ajax call

After ajax call

Answer

Okay, so without completely refactoring your code, I got it to a working state similar to how you have it. You may have to adjust how the page is getting initially set, but the idea is there for you. Your main issue was that you were not updating or passing the next page number through to your functions, so it was reusing the same page number or using undefined each time. There are a few minor changes, so pay close attention to the code below:

'use strict';
$(document).ready(function() {
  bindAllEvents();
});

function nextEvent() {
  this.nextPage = function(page) {
    var url = '/Announcements/Manage'
    var data = [{"WATypeName":"Web Announcements","Categories":[{"ID":6,"Name":"Physician/Medical","IsSelected":true}],"WAID":1,"WADate":"\/Date(1460959200000)\/","WANum":"1123","Topic":"Online Provider Enrollment Summary Page Updated","Link":"web_announcement_1123_20160418.pdf","ToolTip":"Online Provider Enrollment Summary Page Updated","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":11,"Name":"All Providers","IsSelected":true}],"WAID":2,"WADate":"\/Date(1460613600000)\/","WANum":"1122","Topic":"Providers Invited to Complete Health Information Exchange Small Business Impact Questionnaire by April 22, 2016","Link":"web_announcement_1122_20160414.pdf","ToolTip":"Providers Invited to Complete Health Information Exchange Small Business Impact Questionnaire by April 22, 2016","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":8,"Name":"Durable Medical Equipment (DME)","IsSelected":true}],"WAID":3,"WADate":"\/Date(1460613600000)\/","WANum":"1121","Topic":"Attention Provider Type 12: Claims for CPT Codes with Age Restrictions Will Be Enforced","Link":"web_announcement_1121_20160414.pdf","ToolTip":"Attention Provider Type 12: Claims for CPT Codes with Age Restrictions Will Be Enforced","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":4,"Name":"Dental/Orthodontia","IsSelected":true}],"WAID":4,"WADate":"\/Date(1460527200000)\/","WANum":"1120","Topic":"Attention Provider Types 24 and 77: Radiology Codes Billable Effective January 1, 2016","Link":"web_announcement_1120_20160413.pdf","ToolTip":"Attention Provider Types 24 and 77: Radiology Codes Billable Effective January 1, 2016","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":2,"Name":"Outpatient","IsSelected":true},{"ID":6,"Name":"Physician/Medical","IsSelected":true}],"WAID":5,"WADate":"\/Date(1460527200000)\/","WANum":"1119","Topic":"Attention Provider Type 75: Rates for Psychiatric/Substance Abuse Services Updated","Link":"web_announcement_1119_20160413.pdf","ToolTip":"Attention Provider Type 75: Rates for Psychiatric/Substance Abuse Services Updated","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":11,"Name":"All Providers","IsSelected":true}],"WAID":6,"WADate":"\/Date(1460354400000)\/","WANum":"1118","Topic":"EDI Medicare Crossover Claims Notification","Link":"web_announcement_1118_20160411.pdf","ToolTip":"EDI Medicare Crossover Claims Notification","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":6,"Name":"Physician/Medical","IsSelected":true}],"WAID":7,"WADate":"\/Date(1460095200000)\/","WANum":"1117","Topic":"Claims for ICD-10 “Z” Codes and “O09” Codes Billed as the Primary/Principal/First-Listed Diagnosis That Denied Inappropriately Will Be Reprocessed (Updated April 14, 2016)","Link":"web_announcement_1117_20160408.pdf","ToolTip":"Claims for ICD-10 “Z” Codes and “O09” Codes Billed as the Primary/Principal/First-Listed Diagnosis That Denied Inappropriately Will Be Reprocessed (Updated April 14, 2016)","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":11,"Name":"All Providers","IsSelected":true}],"WAID":8,"WADate":"\/Date(1460095200000)\/","WANum":"1116","Topic":"Medicaid Services Manual Chapters 400, 600 and 1900 Updated","Link":"web_announcement_1116_20160408.pdf","ToolTip":"Medicaid Services Manual Chapters 400, 600 and 1900 Updated","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":11,"Name":"All Providers","IsSelected":true}],"WAID":9,"WADate":"\/Date(1460008800000)\/","WANum":"1115","Topic":"Attention Provider Types 23 and 76: Procedure Codes Updated in MMIS","Link":"web_announcement_1115_20160407.pdf","ToolTip":"Attention Provider Types 23 and 76: Procedure Codes Updated in MMIS","WATypeID":1},{"WATypeName":"Web Announcements","Categories":[{"ID":1,"Name":"Inpatient","IsSelected":true},{"ID":2,"Name":"Outpatient","IsSelected":true}],"WAID":10,"WADate":"\/Date(1459922400000)\/","WANum":"1114","Topic":"Attention Provider Types 30 and 83: Service Plans Will No Longer Be Faxed to Providers","Link":"web_announcement_1114_20160406.pdf","ToolTip":"Attention Provider Types 30 and 83: Service Plans Will No Longer Be Faxed to Providers","WATypeID":1}];
    var categories = [{"ID":1,"Name":"Inpatient","IsSelected":false},{"ID":2,"Name":"Outpatient","IsSelected":false},{"ID":3,"Name":"Pharmacy","IsSelected":false},{"ID":4,"Name":"Dental/Orthodontia","IsSelected":false},{"ID":5,"Name":"Vision","IsSelected":false},{"ID":6,"Name":"Physician/Medical","IsSelected":false},{"ID":7,"Name":"Personal Care Services (PCS)","IsSelected":false},{"ID":8,"Name":"Durable Medical Equipment (DME)","IsSelected":false},{"ID":9,"Name":"Behavioral Health","IsSelected":false},{"ID":10,"Name":"Waiver Providers","IsSelected":false},{"ID":11,"Name":"All Providers","IsSelected":false}];
    var _page = page;

    var _model = {
      Data: data,
      Categories: categories,
    };

    $.ajax({
      type: "POST",
      contentType: "application/json; charset=utf-8",
      url: url,
      data: JSON.stringify({ model: _model, page: _page }),
      success: function(result) {
        //console.log("Success " + result);
         $('div#pagination').html($(result).find('div#pagination'));
         $('div#full-table').html($(result).find('div#full-table'));
         $('div#search-form').html($(result).find('div#search-form'));
        _page = parseInt(_page) + 1;   
        bindAllEvents(_page);
      },
      error: function(result) { console.log("Error: " + result.responseText); }
    });
  }
}

function bindAllEvents(page) {
  $('#date-boxes').slideUp(1);

  $('div#pagination').off('click.pagination');
  $('div#pagination').on('click.pagination', '#next', function (e) {
    e.preventDefault();
    var onNextClickEvent = new nextEvent();
    onNextClickEvent.nextPage(page || 2);
  });

  $("a[name='page-number']").off("click.pagination");
  $("a[name='page-number']").on("click.pagination", function(e) {
    e.preventDefault();
    var onPageClick = new pageEvent();
    onPageClickEvent.goToPage($(this).attr('id'));
  });
}