Reputation: 9054
I have a list in asp.net mvc 5
I have limited the number of records to be displayed in page.
now on scroll I do ajax call, the first call works fine but when I scroll down more it recall the function repeatedly 5 to 10 times and lost it again display the data, it was really strange, I could not find solution
My Controller:
public ActionResult Index()
{
int starting = 0;
if (Request.Form["starting"] != null)
{
starting = Convert.ToInt32(Request.Form["starting"]);
}
int takes = 15;
if (Request.Form["takes"] != null)
{
takes = Convert.ToInt32(Request.Form["takes"]);
}
//string strpost = "&ajax=1";
var query = db.MyEmployee.ToList().Skip(starting).Take(takes);
if (Request.IsAjaxRequest())
{
starting = starting+15;
query = db.MyEmployee.ToList().Skip(starting).Take(takes);
ViewData["starting"] = starting;
ViewBag.takes = takes;
return PartialView("_PartialIndex",query);
}
ViewBag.starting = starting;
ViewBag.takes = takes;
return View(query);
}
My Model:
public class Employee
{
public int Id { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
}
My View and partial view code:
<div id="mypage">
@model IEnumerable<MVC5WAuth.Models.Employee>
@{
ViewBag.Title = "Index";
}
<h2>Index 1</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Id)
</th>
<th>
@Html.DisplayNameFor(model => model.FullName)
</th>
<th>
@Html.DisplayNameFor(model => model.Email)
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Id)
</td>
<td>
@Html.DisplayFor(modelItem => item.FullName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
@Html.ActionLink("Details", "Details", new { id = item.Id }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
<script type="text/javascript">
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
// ajax call get data from server and append to the div
var ajax_image = "<img src='../Content/loading.GIF' >";
$('#mypage').html(ajax_image);
var params = '&starting=' + @ViewBag.starting + '&takes=' + @ViewBag.takes;
$.ajax({
url:'@Url.Action("Index", "Employees")',
type: "POST",
data: params,
})
.done(function (r) {
$('#mypage').html(r);
});
}
});
</script>
Upvotes: 3
Views: 2897
Reputation:
You current code is just replacing the existing view each time you scroll and make a ajax call, not updating the existing view with the next set of rows you want. You code also has some inefficiencies such as materializing all your records to an in-memory set before calling .Skip()
and .Take()
.
You need to break this into 2 separate methods and views, one to generate the initial view, and one to return a partial of just the records you want to append to the main view.
Controller
public ActionResult Index()
{
return View();
}
public ActionResult Fetch(int startIndex)
{
query = db.MyEmployee.OrderBy(x => x.ID).Skip(startIndex).Take(15);
return PartialView(query);
}
Index.cshtml
@model IEnumerable<MVC5WAuth.Models.Employee>
....
<table class="table">
<thead>
<tr>
<th>@Html.DisplayNameFor(model => model.Id)</th>
....
</tr>
</thead>
<tbody id="tbody">
@{ Html.RenderAction("Fetch", new { startIndex = 0 }); } // generate the 1st 15 rows
</tbody>
</table>
<script type="text/javascript">
var start = 15;
var url = '@Url.Action("Fetch")';
var tbody = $('#tbody');
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
....
$.get(url, { startIndex: start }, function(response) {
tbody.append(response);
start += 15; // increment for next call
});
}
});
</script>
Fetch.cshtml
@model IEnumerable<MVC5WAuth.Models.Employee>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(m => item.Id)</td>
....
</tr>
}
Upvotes: 1