Refresh Table without refreshing page with html helper PagedListPager - javascript

I have the following line of code which uses html helper's PagedListPager:
#Html.PagedListPager(Model.kyc_paged_list, page => Url.Action("ClientDetails", new { id = ViewBag.ID, kyc_page = page, transaction_page = Model.transaction_page, active = "kyc" }))
When clicking on the the pager the entire page reloads. But I only want the table with id="kyc-history" to refresh.
I know how to reload the table using a JavaScript function but I don't know how to call it from the PagedListPager.
Any ideas how I can call it? Let's say that the JS function is called reloadTable()

I was having the same problem and this article (done by Anders Lybecker) helped me out and now everything working!
It's very clear with steps, But make sure to make backup before starting!
Take a look:
AJAX paging for ASP.NET MVC sites
In summary you make 2 Action Results in your Controler with 2 Views 1 for your page (in my case it's Index View) the other for the List that contain the PagedListPager control (List View). And put the list View inside the Index View. And write the JQuery code for the PagedListPager in the Index View.
You can read the article for the details!
And this is my code with a little extra things I noticed to help you more:
The List View:
#model IPagedList<StudentRegSys.Models.Student>
#{
Layout = null;
}
#using PagedList.Mvc;
#using PagedList;
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400italic,400,600,700" rel="stylesheet">
#Styles.Render("~/template/css")
<div class="container">
<div class="row">
<!-- The List Code-->
<div class="pagination-control">
#Html.PagedListPager(Model, i => Url.Action("List", "Home", new { i, search = Request.QueryString["search"] }))
</div>
</div>
</div>
#Scripts.Render("~/template/js")
Note: Make sure to make Layout = null; and put the Styles Links & the Scripts manual in this View to avoid design issues.
In the Controller: (it's Home Controller in my case)
// GET: /Home/Index
public ViewResult Index()
{
return View();
}
// GET: /Home/List
public ActionResult List(int? i, string search = "")
{
try
{
var students = _context.Student.Include(s => s.Major)
.OrderBy(s => s.Name)
.Where(s => s.Name.Contains(search) || s.Major.Name.Contains(search) ||
s.Address.Contains(search) || s.Phone.Contains(search))
.ToList().ToPagedList(i ?? 1, 8);
return View(students);
}
catch (Exception)
{
return HttpNotFound();
}
}
The Index View:
#{
ViewBag.title = "Home";
}
<section id="intro">
<!-- Some Code -->
</section>
<section id="maincontent">
#Html.Action("List") <!-- to call the List view -->
</section>
<script>
$(document).ready(function () {
$(document).on("click", ".pagination-control a[href]", function () {
$.ajax({
url: $(this).attr("href"),
type: 'GET',
cache: false,
success: function (result) {
$('#maincontent').html(result);
}
});
return false;
});
});
</script>
Note: Make sure to put the html(result) in the root container of the list in my case was <section id="maincontent">.
Hope this help you out :)

Related

Section not defined In Index.cshtml in asp.net mvc?

I define the section in Index. cshtml but when I run the application then generate an error section is not defined
I create the same another project, then define the simple method in Index. cshtml then run my application but my current project popup not be displayed??
another project
_layout.cshtml
<div class="container body-content">
#RenderBody()
#RenderSection("simpelmessage")
<footer>
<p>WebApi Crud Oeperation using Entity Framework In Mvc</p>
</footer>
</div>
Index.cshtml
#section simpelmessage{
<h1>simple message</h1>
}
that is work in another project
but my current working project my popup should not be displayed??
I m performing crud operation using api
_layout.cshtml
<div class="container body-content">
#RenderBody()
#RenderSection("alertpopup")
<footer>
<p>WebApi Crud Oeperation using Entity Framework In Mvc</p>
</footer>
</div>
Index.cshtml
#section alertpopup
{
<script src="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.13.1/alertify.min.js" type="text/javascript">
$(function () {
var successmessage = '#ViewBag.message'
if (successmessage != '')
{
alertify.success(successmessage);
}
});
</script>
}
HomeController.cs
public ActionResult Index()
{
IEnumerable<studentmvcmodel> stdlist;
HttpResponseMessage response = globalvariable.webapiclient.GetAsync("studlogins").Result;
stdlist = response.Content.ReadAsAsync<IEnumerable<studentmvcmodel>>().Result;
ViewBag.message = "record is inserted";
return View(stdlist);
}
public ActionResult create()
{
return View();
}
[HttpPost]
public ActionResult create(studentmvcmodel stud)
{
var username = stud.username;
var passs = stud.password;
if (username != null && passs != null)
{
HttpResponseMessage response = globalvariable.webapiclient.PostAsJsonAsync("studlogins", stud).Result;
ViewBag.message = "data inserted successfully";
return RedirectToAction("Index");
}
else
{
ViewBag.message = "please all the data fillup carefully";
return View("create");
}
}
My record should be created, but I want to popup message when submits the record?? but give the error section is not defined??
What I am trying I went to when I press the submit button, then a popup should be displayed but popup not display?
I hope my question is understood?
I m going to the browser and then ctrl+U then show the popup function.
<script src="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.13.1/alertify.min.js" type="text/javascript">
$(function popup()
{
var successmessage = 'record is inserted';
if (successmessage != '')
{
//alertify.success(successmessage);
alert('record is inserted');
}
});
popup();
</script>
To avoid section is not defined error you need to call RenderSection as below.
#RenderSection("alertpopup", false)
And to make the pop up work, you have defined your javascript function but you are not calling you function anywhere. you can do this instead.
<script src="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.13.1/alertify.min.js" type="text/javascript"></script>
<script>
function popup () {
var successmessage = '#ViewBag.message'
if (successmessage != '')
{
alertify.success(successmessage);
}
}
popup();
</script>
If you return View("create"), so you should render your section in Create.cshtml Or define this #RenderSection("alertpopup", false) in your Layout
Rendering sections take two parameters; a string and a boolean as such:
#RenderSection(string name, bool required)
The name parameter is name of the section to render and required indicates that the section must always be rendered. If the section may not be rendered in some views or sometime, you should set required to false like below.
#RenderSection("alertpopup", false)
I'm also not sure when you want your popup to display because it is not called in your code. If for whatever reason you'll want it to be called when your documents loads, you should change your code to this
#section alertpopup
{
<script src="https://cdnjs.cloudflare.com/ajax/libs/AlertifyJS/1.13.1/alertify.min.js" type="text/javascript">
$(doucument).ready(function () {
var successmessage = '#ViewBag.message'
if (successmessage != '')
{
alertify.success(successmessage);
}
});
</script>
}

How to reload Laravel #includes with AJAX?

I've got a single page application inside of my larger application that will send data to the DB, and will also display that same table's data. Currently, I have AJAX dynamically sending the data. However, to get the data just inserted to appear in the table that I want it to, I have to refresh. I've been trying things all morning, but below is the current state of things.
The View:
<html>
<head>
<!--I took some stuff out to make it easier to look at -->
</head>
<body onresize="resizeRecalc()">
<div class="container-fluid">
<div class="row header">
<div class="col-12">
<img src="{{ URL::asset('images/takeStatsLogo.png') }}" id="header-logo" />
</div>
</div>
<div class="mainArea row">
<div class="left col-8">
<div onclick="playPause()" class="embed-responsive embed-responsive-16by9">
<video id="gameFilm" src="{{ URL::asset('images/basketball.mp4') }}" preload="metadata"></video>
</div>
<div class="timebar">
<span class="timeItem" id="timestamp"></span>
<div onclick="changeVidTime()" onmousemove="moveLine(event)" onmouseout="REmoveLine()" id="outerBox"> <div id="progressBox"> <div id="placeMarker">
</div></div></div>
<span class="timeItem" id="duration-place"></span>
</div>
<!-- This is a key part -->
<div id="statList">
#include('partials.statList')
</div>
</div>
<div id="right" class="right col-4">
<!--Checking if we should make the user select starters. If we have them, no need to do that...-->
#if ($game->starters != null)
#include('partials.areStarters')
#else
#include('partials.noStarters')
#endif
</div>
</div>
</div>
<script>
//Add Stat Form
//This part here will add the stats, but it won't refresh them!
$('input#addStatButton').click( function() {
$.post( '{{action("StatController#store")}}', $('form#new_stat').serialize(), function(data) {
$('#statList').load('/take-stats/{{$game->id}}');
},
'json' // I expect a JSON response
);
clearStat();
});
</script>
<script src="{{ URL::asset('js/takeStats/genJavascript.js') }}"></script>
<script src="{{ URL::asset('js/takeStats/videoJS.js') }}"></script>
<script src="{{ URL::asset('js/takeStats/dataJS.js') }}"></script>
</body>
</html>
Here is the controller method:
public function loadStatList($id) {
$userType = Auth::user()->user_type;
if(Auth::check() && Game::where('id', '=', $id)->exists() && ($userType == 'statistician' || $userType == 'admin')) {
$game = Game::find($id);
$players = $game->team->users->where('user_type', 'player');
$stats = Stat::orderBy('video_timestamp', 'desc')->where('game_id', $game->id)->get();
$statMeta = Stat_Meta::all()->where('type', 'recorded');
return view('partials.statList', compact('game', 'players', 'stats', 'statMeta'));
} else {
abort(404);
}
}
I might be missing something but I thought this would do what I am trying to achieve.
I figured it out!Thank #Get Off My Lawn for giving me a bit of a hint that I couldn't just use the #include. I went ahead and figured out how to pre-render the HTML and then bring it in. It is actually not that hard. The idea here is to use a JQuery function to do an AJAX POST upon hitting submit, then use .done to get then new full webpage. After you have that (you can console.log it to see what you're working with at that point, it will be the entire webpage) you can just get the specific div you want to refresh from the .get you performed, and stick it in the same div. Here is the code:
HTML/#include:
<div id="statList">
#include('partials.statList')
</div>
The AJAX/JQuery:
$('input#addStatButton').click( function() {
$.ajax({
type: 'POST',
url: '{{action("StatController#store")}}',
data: $('form#new_stat').serialize(),
})
.done(function(refresh) {
clearStat();
$.get('{{action("StatController#show", [$game->id])}}', function(data) {
var newData = $("#statList" , data)
$( "#statList" ).html( newData );
//console.log(newData);
});
});
});
I'M SO HAPPY Y'ALL!!!
As discussed this is not an answer on your question but a simple explanation you asked in the comments. And it can help somebody else
Laravel and JQuery
How powerfull :-)
First i will try to fit this as much as possible to your needs with the information your provided.
Secondly jquery contains some cool ass functions a lot of people don't know about.
As you described you have a single page website or something like that. That means you have 1 route to show the single page i suggest /take-stats/{{$game->id}}.
In your controller and i use as example the GameController you have something like the following.
class GameController
{
public function __construct()
{
}
//the single page view
public function index()
{
//your singlepage logic here....
return view('games.index'); //something like this?
}
public function create() //this is where you post to
{
//logic to store the game stats...
//this is where you return a succes message or something.
//lets return the index instead :-)
//dont't return $this->index! use redirect to the route.
return redirect()->route('the.route.to.your.index');
}
}
As you see above, we return the single page in the post response. SSo when you post to the store method, and it succeeds it returns the index page.
Now the jquery.
$('input#addStatButton').on( function() {
//this is where to do the post.
$.post(`{{ route('to.your.store.route') }}`, $('form#new_stat').serialize(), (response) => {
//clear the stats because the post is succeeded in here
//also reload the content. The response contains the new html content
//now what we can do is replace the whole content....
//something like $(`html`).html('response);
//or we get the content we need from the response and this is where jquery comes in handy. The response is simply a html response so jquery can create a new dom from it.
let statsList = $(response).find(`#statslist`).html(); //create a dom element of the response.
$(`#statslist`).html(statslist); //put the filtered html in the current list.
//thats all :-)
}).fail(() => {
// a fail save. When the post fails it will come in here.
}).always(() => {
clearStats();
//this is called always even when it fails. You can clear the stats or something in here.
});
});
A short description :
Onclick post button, post to post.route
Controller method does logic and returns as success the index url.
jquery parses the html response and replaces the original content.
done.
I hope this helps you or somebody else. When using a structure like above this code is simply cleaner and faster for it only executes one request.

JavaScript isnt getting called before the Html

I have a script in my header that is calling a web api which should populate a view model. This is below.
#using GigHub.Controllers
#using GigHub.ViewModel
#model GigHub.ViewModel.ProjectsViewModel
#{
ViewBag.Title = "Projects";
}
<head>
<script>
(function getProjects() {
$.get("/api/projects")
.done(function () {
alert("Got Projects");
})
.fail(function () {
alert("Something failed!");
});
});
</script>
</head>
I then have my html that would loop through the viewModel and set it up throughout the html, but every time it gets run, it is throwing a null reference exception to Model.ProjectList in the for each because it hasn't populated yet. I thought putting the script in the header would let it run first, but that doesn't seem to be the case.
<h2>Projects</h2>
<ul class="gigs voffset4" style="width: 600px;">
#foreach (var project in Model.ProjectList)
{
<li>
<div class="date">
<div class="month">
#project.Name
</div>
<div class="day">
#project.Key
</div>
</div>
<div class="details">
<span class="artist">
#project.Id
</span>
<span class="genre">
#project.ProjectTypeKey
</span>
</div>
</li>
}
</ul>
Here is my actual projectsController
public class ProjectsController : Controller
{
private readonly string m_Username = Properties.Settings.Default.username;
private readonly string m_Password = Properties.Settings.Default.password;
public ActionResult Index()
{
var client = new RestClient("https://example.net/rest/api/2/");
client.Authenticator = new HttpBasicAuthenticator(m_Username, m_Password);
var request = new RestRequest("project/", Method.GET);
request.RequestFormat = DataFormat.Json;
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
var response = client.Execute<List<Project>>(request);
var content = response.Content; // raw content as string
if (content == null)
throw new Exception(response.ErrorMessage);
var projectArray = JsonConvert.DeserializeObject<List<Project>>(response.Content);
var viewModel = new ProjectsViewModel()
{
ProjectList = projectArray,
Heading = "Projects"
};
return View("Projects", viewModel);
}
}
You are trying to mix javascript and C# code together and expecting it to work! No. It does not work that way.
The c# code in your view ( the foreach block) gets executed by razor in the server and the resulted html markup will be send to the client browser. That means, if you are accessing Model.ProjectList in your view, you should make sure that you are passing a model to your view with that property(ProjectList).
You have 2 options.
1. Full server side approach
In your get action, create an object of your view model, set the ProjectList property and send it to view.
public ActionResult Index()
{
var vm = new YourViewModel();
vm.ProjectList= GetListOfProjectsFromSomeWhere();
return View(vm);
}
private List<ProjectItem> GetListOfProjectsFromSomeWhere()
{
var list=new List<ProjectItem>();
list.Add(new ProjectItem { Name="Project 1"}); // Replace with real data here
return list;
}
Assuming you have a view model called YourViewModel as below
public class ProjectItem
{
public string Name {set;get;}
}
public class YourViewModel
{
public List<ProjectItem> ProjectList {set;get;}
}
and
and make sure your razor view is strongly typed to this view model
#model YourViewModel
<h2>Projects</h2>
#foreach (var project in Model.ProjectList)
{
<p>#project.Name</p>
}
2. Use ajax to load page content.
From your client side code,make the call to your api(like you did) and parse the response and update the DOM.
You need to create a container element in your view so that your javascript code can append items to that from the api call result.
<ul id="projects"></ul>
Now make sure that your javscript code will execute on the document ready event.
function getProjects() {
$.get("/api/projects")
.done(function (data) {
var projectHtml="";
$.each(data,function(i,item){
projectHtml+="<li>"+item.Name+"-"+item.Key+"</li>";
});
$("#projects").html(projectHtml);
})
.fail(function () {
alert("Something failed!");
});
}
$(function(){
getProjects();
});
Assuming your api call returns an array of item, each with a Name & Key property like this
[{Name:"Project1", Key:"Pr1"},{Name:"Project2", Key:"Pr2"}]

Ajax.ActionLink Only Links to the Current Page

I have an Ajax.ActionLink in a Partial View as follows:
<div id="accordion">
#foreach (var m in Model)
{
var targetId = m + "_List";
<h3 id="#(m)" class="thingModelHeader">
#Ajax.ActionLink(m, "AjaxGetThings", "Perf",
new AjaxOptions {
HttpMethod="GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId= targetId,
Url="13412"
})
</h3>
<div id="#targetId" >
#* list will populate here when the link is clicked *#
</div>
}
</div>
I have a controller with the appropriate method:
public class PerfController : Controller
{
[Route("AjaxGetThings/{id}", Name = "AjaxGetThings")]
public PartialViewResult AjaxGetThings(string id)
{
IQueryable<Thing> results;
using (var repo = new ReadOnlyRepository<Thing>())
{
things = repo.All()
.Where(p => p.Id == Id)
.OrderBy(p => p.Name)
;
}
return PartialView("CustomPartialView", results);
}
}
I have a ScriptBundle for the unobtrusive validation:
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"));
...and I reference it in my Layout page:
</footer>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jquery-ui")
#Scripts.Render("~/bundles/jqueryval")
#RenderSection("scripts", required: false)
</body>
</html>
The problem is that no matter how I define the Action, Controller, or Url in the AjaxOptions the link always points to the current URL. The target div loads and updates with a whole 'nuther version of the page - so it's working as far as the Ajax part of it goes, but no matter what I do the URL never points anywhere useful - like the actual controller and action that I have specified.
try specifying the url like this
url: 'Url.Action("Action", "Controller", new { ID = m.targetid })'

MVC 4 - Bootstrap Typeahead source with an ActionResult

I'm using MVC 4 and Entity Framework to develop an intranet web app. On one of my views, I have to implement the autocomplete feature. To do that, I'm using Bootstrap Typeahead. I tried to pass my action (so my function) to feed the input element but it seems that it doesn't work.
Here is my action result which returns an Json :
public ActionResult AutoComplete(string term)
{
var result = db.Persons.Where(p => p.FirstName.ToLower().Contains(term.ToLower()) || p.LastName.ToLower().Contains(term.ToLower())).ToList().Select(p => p.FullName).ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
My View and my script :
#model IEnumerable<BuSIMaterial.Models.Person>
#{
ViewBag.Title = "Index";
}
<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />
<h2>Index</h2>
<input type="text" class="typeahead" data-provide="typeahead">
#section Scripts
{
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jqueryui")
#Styles.Render("~/Content/themes/base/css")
$(".typeahead").typeahead({
source: function (query, process) {
var persons = [];
map = {};
// This is going to make an HTTP post request to the controller
return $.post('/Person/AutoComplete', { query: query }, function (data) {
// Loop through and push to the array
$.each(data, function (i, person) {
map[person.Name] = person;
map[person.F]
persons.push(country.Name);
});
// Process the details
process(countries);
});
},
updater: function (item) {
var selectedShortCode = map[item].ShortCode;
// Set the text to our selected id
$("#details").text("Selected : " + selectedShortCode);
return item;
}
});
</script>
}
In my master page, I call the Bootstrap jquery file(s). Any idea about what's going on?

Categories

Resources