Asp.NET MVC – JQuery İle Scroll Paging(Sayfalama)
Web sayfalarında verilerimizi listelerken sayfalamaya ihtiyaç duyuyoruz.Bu ihtiyacın temel kaynağı binlerce veriyi tek sayfada yoğunlaştırıp kullanıcıları yormamak olsa da serverdan gelen veri yoğunluğunu azaltmak ve sayfa oluşum aşamasındaki negatif etkileri ortadan kaldırmak gibi faktörlerde işin içine girmektedir.Bu durumda düzinelerce sayfalama yöntemleri ve algoritmaları mevcuttur.Tabi ki de bu algoritmalardan bir tanesinide kendinize özgü oluşturabilirsin.Bu hususta hiç bir sınırlama olmaksızın daha görsel ve animasyonel yapılar barındıran yöntemlerde icat edebilirsiniz.Velhasıl, şahsın biri düşünmüş ve Scroll Paging diye isimlendirdiğimiz animasyonda tavan yapan bir listeleme mantığı oluşturmuş.Aslında bu yapıyı Facebook kullanıcıları kullanmakta ve bazı internet sitelerinde de karşımıza çıkmaktadır.Bu makalemizin içeriğinde Scroll Paging nasıl yapıldığını detaylı bir biçimde adım adım irdeleyeceğiz.
Öncelikle bilmeyenler için Scroll Paging nedir izah edelim.
Scroll Paging, bir sayfada listelenen verileri scrollbar aracılığıyla sayfalamaktır.Scrollbar sayfanın sonuna geldiğinde listelenen verinin devamını dinamik olarak Ajax ve JQuery yardımıyla ilgili alana basmaktır.Hızlı örnek vermek gerekirse, Facebook anasayfasına girin ve scrollbar’ı sayfanın en aşağısına indirin.Kısa bir yüklemeden sonra hızlıca önceki yayın akışı karşınıza gelecektir.İşte şimdi bu mekanizmayı bu makalede teknik olarak tanımlayacağız. 😉
Yukarıda değindiği gibi Scroll Paging işlemi için Ajax ve JQuery’den yardım alacağız.Makalemizde örneklendirmeyi Northwind veritabanıyla gerçekleştireceğiz.Hadi başlayalım…
Öncelikle Visual Studio platformunda Asp.NET MVC projesi oluşturup anında Models katmanına bir Linq To Sql dosyası atıyoruz ve Northwind veritabanındaki Musteriler isimli tabloyu projemize entegre ediyoruz.
İşlemlerimizi örneklendirmek amaçlı bu tablo üzerinden gerçekleştireceğiz.
“Home(Controller).cs” isimli Controller sınıfı oluşturup, içerisindeki “Index” Action metodu üzerinde bu işlemi gerçekleştireceğim.Sizler kendi çalışmanıza göre uyarlayabilirsiniz.Bu makalenin tüm mevzusu bu Action görüntüsü üzerinde dönecektir.
Öncelikle “Index” Action’ımızı aşağıdaki gibi oluşturuyorum.
public class HomeController : Controller { VeriTabaniDataContext Veri = new VeriTabaniDataContext(); int SayfaBoyutu = 10;//Bir sayfada kaç adet listeleme yapılacak. public ActionResult Index(int? sayfano) { List<Musteriler> MusteriListesi = null; if (sayfano == null) { MusteriListesi = Veri.Musterilers.OrderByDescending(m => m.MusteriID).Take(SayfaBoyutu).ToList(); } else { MusteriListesi = Veri.Musterilers.OrderByDescending(m => m.MusteriID).Skip(SayfaBoyutu * sayfano.Value).Take(SayfaBoyutu).ToList(); } if (Request.IsAjaxRequest()) { return PartialView("~/Views/Home/Partial/PartialMusteriler.cshtml", MusteriListesi); } return View(MusteriListesi); } }
Yukarıdaki kod bloğunu siz incelerken ben izah edeyim.
- 4. Satır‘da, her listeleme esnasında kaç veri getirileceğini tutuyoruz.
- 11. Satır‘da, eğer sayfano isimli değişken null ise demek oluyor ki sayfalama talep edilmemiştir.O yüzden başlangıç olarak ilk 10 elemanı elde ediyoruz.
- 15. Satır‘da, eğer sayfano isimli değişken null değil ise demek oluyor ki sayfalama talep edilmiştir.O anki sayfano değişkeniyle SayfaBoyutu değişkeninin değerleri çarpıyoruz ve çıkan sonucu Skip metodu ile başlangıç kabul edip, Take komutu ile SayfaBoyutu değeri kadar yani 10 adet elemanı elde ediyoruz.
- 18. Satır‘da, sayfanın Ajax ile talep edilip edilmediğini kontrol ediyoruz.Burası tekniğimizin en can alıcı komutudur.Sayfa ilk açıldığında Ajax tarafından talep edilmeyecektir.Haliyle ilk 10 veri direkt olarak normal bir Get işlemiyle listelenecektir.Halbuki olay sayfa talep etmeye geldiğinde ki bu sayfa taleplerini birazdan Ajax ile gerçekleştireceğimiz için bu taleplerin Ajax formatlı olup olmadığını kontrol etmemiz gerekmektedir.Bu satırda yapılan kontrol sayesinde hem sayfalamanın talep edildiğini anlayacağız hemde bu talebin Ajax ile gerçekleştirildiğini bileceğiz.
- 20. Satır‘da, eğer bu Action Ajax ile talep edildiyse bu demek oluyor ki sayfalama talep edilmiştir.Bunu yukarıda da dediğim gibi View katmanında birazdan gerçekleştireceğiz.Haliyle bu talep neticesinde elde ettiğimiz verileri ilk etapta var olan verilerin altına bastıracağız.Hatta ilk etapta demekten ziyade, önceki yazdırılan verilen üzerine bastıracağız demek daha doğrudur.Bunuda PartialView göndererek gerçekleştireceğiz.Satırda gördüğünüz PartialView’e verilen dizindeki dosyayı birazdan oluşturacağız.Şimdilik adresini vermemiz yeterlidir.
- 22. Satır‘da, eğer Action Ajax ile tetiklenmemişse bunu ilk açılış olarak görüyor ve ilk 10 nesne dolu listeyi normal bir şekilde View’a gönderiyoruz.
Evet, artık Controller katmanımız tüm işlemlerimiz için hazır.Şimdi sıra geldi View katmanını düzenlemeye.
“Index” Action metodun View katmanındaki “.cshtml” uzantılı dosyasını oluşturuyoruz.Ayriyetten, yukarıda 20. satırda dizinini belirttiğimiz PartialView’i de benzer dizinde “PartialMusteriler” adında oluşturuyoruz.Burada kafanız karışırsa eğer siz direkt olarak “~/View/Home/—PartialAdi—.cshmtl” olarakta oluşturabilirsiniz.Ben genellikle Partial’ları ilgili View katmanının altında bir Partial isimli klasör oluşturarak tuttuğum için makalede de aynı şekilde örneklendirmekteyim.
Öncelikle “PartialMusteriler” isimli Partial dosyamızı aşağıdaki gibi düzenleyelim.
@model IEnumerable<Calisma.Models.Musteriler> @foreach (var item in Model) { <div style="width:300px;border:ridge;"> <p><strong>Müşteri Adı : </strong>@item.MusteriAdi</p> <p><strong>Adres : </strong>@item.Adres</p> <p><strong>Posta Kodu : </strong>@item.PostaKodu</p> </div> }
Şimdi de “Index” isimli View dosyamızı aşağıdaki gibi düzenleyelim.
@model IEnumerable<Calisma.Models.Musteriler> <div style="border-style:ridge;width:300px;background-color:black;color:white;font-size:25px;">Müşteri Listesi</div> <div id="MusteriListesi"> @Html.Partial("~/Views/Home/Partial/PartialMusteriler.cshtml", Model) </div>
Şimdi bu şekilde projemizi derleyip çalıştırdığımız zaman ilk 10 veriyi ekranda göreceğiz.
Artık Scroll Paging ile geri kalan verilerimizi onar onar çekelim.
<script type="text/javascript"> var SayfaSayisi = 0; $(window).scroll(function () { //Scroll hareket ettiği zaman devreye girer. if ($(window).scrollTop() == $(document).height() - $(window).height()) { //Bu algoritma ile ScrollBar'ın sayfanın en aşağı indiği anı yakalarız. $.ajax({ url: '/Home/Index', data: { sayfano: SayfaSayisi }, //Index Action metodunun aldığı sayfano isimli parametreye SayfaSayisi değişkenindeki değeri gönderiyoruz. success: function (data) { $("#MusteriListesi").append(data); SayfaSayisi++; } }); } }); </script>
- 2. Satır‘da, o anki sayfanın ne olduğunu belirtiyoruz.Her Ajax işlemi sonucu arttırılmaktadır.
- 4. Satır‘da, ScrollBar her hareket ettiğinde çalışacak JQuery bloğudur.
- 6. Satır‘da, ScrollBar’ın her hareketinde işlem yapmayacağız.Bizim amacımız ScrollBar’ın sayfanın en aşağısına indiğinde tetiklenecek bir olaydır.O yüzden bu satırdaki algoritmayla ScrollBar’ın sayfanın en altında olduğunu hesaplamış oluyoruz.
- $(window).scrollTop() komutu, ScrollBar’ın üst noktasıyla tarayıcı arasındaki mesafeyi matematiksel verir.
- $(document).height() komutu, sayfanın ScroolBar ile olan dik uzunluğunu verir.
- $(window).height() komutu, sadece tarayıcıdaki ekranın dik uzunluğunu verir.
Bu üçlü değişken ile gördüğünüz gibi yapılan kombinasyonla ScrollBar’ın sona geldiğini hesaplayabiliyoruz.
- 13. Satır‘da, yapılan Ajax işlemi sonucu PartialView olarak gelen veriyi “MusteriListesi” id değerine sahip div elemanına append ile ekliyoruz.append fonksiyonu var olan verilerin altına ekleme işlemi gerçekleştiriyor.
- 14. Satır‘da, bir sonraki sayfalama talebi için SayfaSayisi isimli değişkenin değerini 1 arttırıyoruz.
Bu şekilde projemizi derleyip çalıştırdığımız zaman Scroll Paging işleminin başarıyla çalıştığını göreceksiniz.Lakin burada bir olası hatayı bilinçli bir şekilde es geçmiş bulunmaktayım.Aslında buna hata demek yanlış olacaktır.Buna bir performans kaybı ya da lüzumsuz server işlemi diye isim verebiliriz.Burada olayımız şudur.Scroll Paging ile ScrollBar’ı aşağı indirdikçe verilerinizi listeleyiniz.Sonuna kadar!!!En sonunda Server’dan liste boş geleceği için Scroll Paging işlemi yapılmayacaktır.Lakin ScrollBar her sayfanın sonuna geldiğinde Index Action’ı yeniden tetiklenecek ve serverda lüzumsuz bir iş yükü ortaya çıkacaktır.Bu durumu performanstan tutun, sistemin trafiğine kadar negatif sonuçlar doğurabilir.O yüzden script komutlarımızda aşağıdaki güncellemeyi gerçekleştirelim.
<script type="text/javascript"> var SayfaSayisi = 0; var SayfaPost = true; //Sayfa hala Post edilebilir durumda mı değil mi kontrolü sağlayan değişkendir. $(window).scroll(function () { if ($(window).scrollTop() == $(document).height() - $(window).height()) { if (SayfaPost) { $.ajax({ url: '/Home/Index', data: { sayfano: SayfaSayisi }, success: function (data) { if ($.trim(data) == '') { //Server'dan gelen veri boş ise SayfaPost = false; //SayfaPost değişkenini false yap.Bu sayede bir daha Server tetiklenmeyecektir. } else { $("#MusteriListesi").append(data); SayfaSayisi++; } } }); } } }); </script>
Evet, artık Scroll Paging ile sayfalamayı gerçekleştirip, listenin sonuna gelindiğinde de serverı tetiklemeyi durdurmuş olduk.
Aslında yazımız içerik olarak burada son bulmaktayken ek olarak görsellik katacak bir durumu eklemeyi göz ardı etmiyorum.Scroll Paging yapılırken verilerin bodoslama ilgili alana yapıştırılması hiç hoş gözükmemektedir.Bu işlem esnasında “Yükleniyor…” gibisinden bir pencere oldukça şık olabilir.
Aşağıda oluşturmuş olduğum div elemanını Index.cshtml sayfanızda herhangi bir yere ekleyiniz.
<div id="pencere" style="display:none;width:133px;height:25px;border:0 solid black;position:fixed;top:50%;left:50%;padding:2px;text-align:center;"> Yükleniyorrrrr.... </div> Şimdide script kodlarımızı aşağıdaki gibi güncellersek eğer her Scroll Paging işleminde "Yükleniyor" mesajı verilecektir. <script type="text/javascript"> var SayfaSayisi = 0; var SayfaPost = true; $(window).scroll(function () { if ($(window).scrollTop() == $(document).height() - $(window).height()) { $("#pencere").show(); //ScrollBar sona geldiğinde pencereyi göster... if (SayfaPost) { $.ajax({ url: '/Home/Index', data: { sayfano: SayfaSayisi }, success: function (data) { if ($.trim(data) == '') { SayfaPost = false; } else { $("#MusteriListesi").append(data); SayfaSayisi++; } $("#pencere").hide(); //Ajax işlemleri bittirip, sayfalama neticesinde ilgili verilerin ilgili alana bastırılmasından sonra pencereyi kapat. } }); } } }); </script>
Bu işlemden sonra makalemizin sonuna gelmiş bulunmaktayız.Son kez aşağıdaki videodan bu yapının nasıl çalıştığını net bir şekilde irdeleyebilirsiniz.
Sonraki yazılarımda görüşmek üzere...
İyi çalışmalar...
Hocam ben mvc bilmiyorum ve sitemi de eski düzen asp.net ile tasarladım bunu o şekilde yazmamız mümkünmü acaba?
Mümkün ama benden tavsiye tasarımı MVC tabanlı boş bir projeye taşıyıp sıfırdan kodlamanı söylerim.
Hocam scroll bar ortalara geldiğinde kayıtları göstermek istiyorum ne yapmam gerek?
Selam hocam bilgi için teşekkürler. Bir sorum olacak Telefondan yada tabletten girince çalışmıyor sayfanın sona gelip duruyor yeni verileri çekmiyor sorun neyden kaynaklı olabilir. Teşekkürler
Merhaba,
Sorun birçok faktörden kaynaklanıyor olabilir. Ne söylesek teoride kalır.
Hocam biraz inceledim $(window).scrollTop() == $(document).height() – $(window).height() sonucu eşitlenmiyor scrolltop() mobilde daha küçük sonuç veriyor. sayı verip çıkarma işlemi yaptım ama sonuc çalışmadı.
Hmm… Yüzdelik olarak doğru bir kombinasyon uygulanması lazım olabilir.
Bunu Projemde uyguladım.Çalişiyor ama nerdeyse 1 dakkika bekliyorum bekliyorum.Hata almıyorum.Neden olabilir acaba ?
Birçok nedenden olabilir. Hem jQuery hem de Backend kodlarınıza göz atılması gerekmektedir.
Bunu asp.net core da ve partialview kullanmadan normal bir view üzerinde nasıl yapabiliriz. Senaryo şu:
Üstte bir selectlist departmanları içeren.
SelectList’ten seçim yapıyorum. jquery ajax ile o departmanda çalışan personeller dinamik olarak bir html table da listelenecek şekilde.
Merhaba,
Verileri JSON formatında elde ederek istediğiniz alanda listeleyebilirsiniz.
Örnek olarak şu adresteki içeriği inceleyebilirsiniz.
her defasında sayfano değişkenini sıfır olarak gönderiyor. Artmıyor hiç. ++ komutunu da uyguladım kodda bir yanlıslık yok ama nedne böyke oldu bilemedim.
Hocam elinize sağlık,faydali bir yazı olmuş.
Hocam merhabalar, bu yöntem masaüstünde düzgün çalışıyor ama siteyi mobilde açtığımız zaman aynı üürünleri getiripduruyor habire. Üstüne totalde olan ürün sayısından fazla ürünü getiriyor bir de. Sebebi ne olabilir=?
Eline sağlık gayet açıklayıcı olmuş.
Teşekkürler