Reputation: 3707
I'm trying my hand at MVC and loading a partial view with Ajax. I've found a bunch of different examples but none that have hit what I'm looking for, at least none that I've found.
What I'm trying to do is create a Report page that the top section will have user selections (Start/End date, pay code, city) and then I would like to call a controller with jQuery/Ajax, get the data, populate the partial view, and display it below the user selections.
So what I have now will throw an error with Javascript (all I get is the alert that says "error") but then it will load the partial page as a whole separate page. I'm assuming the AJAX portion is failing but then it moves on to the server side of the controller's POST and it's just loading the Partial View. I'm hoping to get the Partial View to load in the <div id="reportResults">
.
I think one of the first things that I have wrong is that I'm using an MVC HTML.Form. That POST will go to the controller but I'm thinking since I'm trying to use Ajax I wouldn't use an MVC form?
I also have one ViewModel (TotalHoursReportVM) that is used for the User Selections when the end user comes to the page and then another ViewModel (TotalHoursReportRecord) for getting the records of the actual report. Since my main View is looking for the TotalHoursReportVM obviously gives me an error if I try to pass the TotalHoursReportRecordVM to the Partial View. So, I don't know I should combine these or if I even should?
I've looked at so many articles and tried a handful of things to a point that I'm frustrated and confused as to what I'm doing. Hopefully someone can shed some light for me or point me to an example to look at.
Here is my main View. This just has a Start/End Datapicker, a couple drop down lists and submit button.
@model PayrollReports.ViewModels.TotalHoursReportVM
@{
ViewBag.Title = "Total Hours";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section scripts
{
<script src="@Url.Content("~/Scripts/Views/TotalHoursReport.js")"></script>
}
<h2>Total Hours Report</h2>
<div class="container">
@using (Html.BeginForm("TotalHoursRun", "Report", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary("Report creation was unsuccessful. Please correct the errors and try again.")
<form class="form-horizontal" role="form">
<div class="form-group">
<div class="row voffset3">
<div class="col-md-2 text-left">
<div id="startDatepicker" class="input-group date">
<input class="datepicker form-control" type="text" />
<div class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</div>
</div>
</div>
<div class="col-md-2">
<div id="endDatepicker" class="input-group date">
<input type="text" class="form-control">
<div class="input-group-addon">
<div class="glyphicon glyphicon-calendar"></div>
</div>
</div>
</div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
<div class="form-group">
<div class="row voffset3">
<div class="col-md-4 text-left">
@Html.DropDownListFor(m => m.SelectedPayCode,
new SelectList(Model.PayCodes, "PAY_CODE", "PAY_CODE"),
"-- Select Pay Code --",
new { style = "width:200px;height:30px" })
</div>
<div class="col-md-4">
<div id="templateGroup" style="display:none;">
Available templates<br />
<select id="dropdowntipo">
<option value="Exemplo1">Exemplo1</option>
<option value="Exemplo2">Exemplo2</option>
<option value="Exemplo3">Exemplo3</option>
</select>
</div>
</div>
<div class="col-md-4"></div>
</div>
</div>
<div class="form-group">
<div class="row voffset3">
<div class="col-md-4 text-left">
@Html.DropDownListFor(m => m.SelectedCityCode,
new SelectList(Model.CityCodes, "CityCode", "CityCode"),
"-- Select City --",
new { style = "width:200px;height:30px" })
</div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
<div class="form-group">
<div class="row voffset4">
<div class="col-md-4 text-left">
<button type="submit" id="btnRunReport" class="btn btn-primary">Run Report</button>
<button type="submit" id="btnTemplate" class="btn btn-default">Template</button>
</div>
<div class="col-md-4 text-left">
</div>
<div class="col-md-4"></div>
</div>
</div>
</form>
}
<div id="reportResults">
</div>
</div>
Here is my partial View:
@model IEnumerable<PayrollReports.ViewModels.TotalHoursReportRecord>
<hr />
<div id="divgrid" style="margin-top: 15px;">
@{
var grid = new WebGrid(Model, canPage: true, rowsPerPage: 5, selectionFieldName: "selectedRow", ajaxUpdateContainerId: "gridContent");
grid.Pager(WebGridPagerModes.NextPrevious);}
<div id="gridContent">
@grid.GetHtml(
tableStyle: "webgrid-table",
headerStyle: "webgrid-header",
footerStyle: "webgrid-footer",
alternatingRowStyle: "webgrid-alternating-row",
selectedRowStyle: "webgrid-selected-row",
rowStyle: "webgrid-row-style",
columns: grid.Columns(
grid.Column("EmployeeId", "Employee", style: "id"),
grid.Column("FirstName", "First Name", style: "PName"),
grid.Column("LastName", "Last Name", style: "PName"),
grid.Column("PayCode", "Pay Code", style: "IName"),
grid.Column("PayHours", "Pay Hours", style: "Weight")
))
</div>
</div>
Here is my Controller:
namespace PayrollReports.Controllers
{
public class ReportController : Controller
{
ReportRepository repo = new ReportRepository();
// GET: Report
public ActionResult TotalHours()
{
TotalHoursReportVM model = new TotalHoursReportVM();
return View(model);
}
// POST: Report/TotalHoursRun
[HttpPost]
public ActionResult TotalHoursRun(DateTime? startDate, DateTime? endDate)
{
try
{
if (ModelState.IsValid)
{
var data = repo.GetTotalHoursData();
return PartialView("_TotalHoursGrid", data);
}
return View();
}
catch
{
return View();
}
}
}
Here is my Repository:
public IEnumerable<TotalHoursReportRecord> GetTotalHoursData()
{
List<TotalHoursReportRecord> listHours = new List<TotalHoursReportRecord>();
DateTime startDate = new DateTime(2015, 1, 4);
DateTime endDate = System.DateTime.Today;
using (DataContext db = new DataContext())
{
var payCodes = new string[] { "REG", "AST", "OT" };
var companyCode = new string[] { "SM00", "EA00", "EX00" };
listHours = (from h in db.HOURS
join e in db.SAP_EMPLOYEE on h.EMP_ID equals e.EMP
where companyCode.Contains(e.CO)
&& h.OCCURRENCE_DATE >= startDate
&& h.OCCURRENCE_DATE <= endDate
&& payCodes.Contains(h.PAY_CODE)
select new TotalHoursReportRecord
{
EmployeeId = h.EMP_ID,
FirstName = e.FIRST_NAME,
LastName = e.LAST_NAME,
PayCode = h.PAY_CODE,
PayHours = h.PAY_HOURS,
OccurrenceDate = h.OCCURRENCE_DATE,
CityCode = e.CITY_CODE
}).OrderBy(o => o.LastName)
.ThenBy(o => o.FirstName)
.ThenBy(o => o.OccurrenceDate)
.ThenBy(o => o.PayCode).ToList();
}
return listHours;
}
Here is my ViewModel
namespace PayrollReports.ViewModels
{
public class TotalHoursReportVM
{
public int ReportID { get; set; }
[Required]
public DateTime StartDate { get; set; }
[Required]
public DateTime EndDate { get; set; }
[Required]
public string PayCode { get; set; }
[Required]
public string City { get; set; }
public IEnumerable<APAY_CODES> PayCodes { get; set; }
public int SelectedPayCode { get; set; }
public IEnumerable<CityCodeVM> CityCodes { get; set; }
public int SelectedCityCode { get; set; }
public IEnumerable<TotalHoursReportRecord> TotalHoursReportRecord { get; set; }
public TotalHoursReportVM()
{
var repo = new ReportRepository();
PayCodes = repo.GetPayCodes();
CityCodes = repo.GetCityCodes();
}
}
public class CityCodeVM
{
public string CityCode { get; set; }
}
public class TotalHoursReportRecord
{
public string EmployeeId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PayCode { get; set; }
public decimal PayHours { get; set; }
public DateTime OccurrenceDate { get; set; }
public string CityCode { get; set; }
public decimal TotalHours { get; set; }
}
}
Here is my JavaScript:
$(document).ready(function () {
//Datepicker
var startDate = new Date();
startDate.setDate(startDate.getDate() - 7);
var endDate = new Date();
$("#startDatepicker").datepicker("setDate", startDate);
$("#startDatepicker").datepicker("update");
$('#startDatepicker').datepicker().on('changeDate', function (ev) {
$('#startDatepicker').datepicker('hide');
});
$("#endDatepicker").datepicker("setDate", endDate);
$("#endDatepicker").datepicker("update");
$('#endDatepicker').datepicker().on('changeDate', function (ev) {
$('#endDatepicker').datepicker('hide');
});
$('#btnRunReport').click(function () {
/*GET*/
var start = $('#startDate').val();
var end = $('#endDate').val();
$.ajax({
url: '/Report/TotalHoursRun',
contentType: 'application/json; charset=utf-8',
dataType: "html",
type: "GET",
data: { startDate: start, endDate: end },
success: function (result) {
alert(data);
},
error: function (xhr, status)
{
alert(status);
}
});
});
Upvotes: 0
Views: 1465
Reputation: 417
You could try something like this:
change
<button type="submit" id="btnRunReport" class="btn btn-primary">Run Report</button>
to
<a class="btn btn-primary" href="#" id="btnRunReport" >Run Report</a>
in your ajax call changes
$('#btnRunReport').click(function (e) {
/*GET*/
e.preventDefault();
var start = $('#startDate').val();
var end = $('#endDate').val();
$.ajax({
url: '@Url.Action("TotalHoursRun", "Report")',
dataType: "html",
type: "GET",
data: { startDate: start, endDate: end },
success: function (result) {
$("#reportResults").html(result);
},
error: function (xhr, status)
{
alert(status);
}
});
});
in your controller
public ActionResult TotalHoursRun(DateTime? startDate, DateTime? endDate)
{
var data = repo.GetTotalHoursData();
return PartialView("_TotalHoursGrid", data);
}
Upvotes: 1