I am trying to add a simple checkbox feature to each day in my calendar view. It must be inline with the style of the current calendar and when a bool is selected it must be able to save the changes to the database. Any suggestions would be appreciated.
My main issue at the moment is the checkboxes that are being selected are not being saved to the db.
Controller.cs
private F2FW _db = new F2FW();
[HttpGet]
public ActionResult CalendarIndex()
{
List<Event> events = new List<Event>();
Project.Models.Calendar calendar = new Project.Models.Calendar();
calendar.SetDate(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
calendar.View(#"~\Views\Patient\Calendar.cshtml");
calendar.ViewData.Add("events", events);
ViewBag.calendar = calendar.Render();
return View(calendar);
}
[HttpPost]
public ActionResult CalendarIndex(User user, CalendarArg calArg, int dayCounter, string[] cbx_day, Patient patient, SessionExercise sessionExercise)
{
SessionInformation sessiondata = new SessionInformation();
Session lastsession = db.Sessions.Where(s => s.ActiveUserID == user.UserID).OrderByDescending(e => e.StartedAt).FirstOrDefault();
calArg.CompletedToday = DateTime.Today;
if (ModelState.IsValid)
{
if (calArg.CompletionRequested == false)
{
//do nothing!
}
else if (calArg.CompletionRequested == true)
{
if (sessiondata.Completed == true)
{
if (sessionExercise.FinishedAt == calArg.Past)
{
List<Event> events = new List<Event>();
events.Add(new Event() { Title = "Exercises Completed", EventDate = DateTime.Now.AddDays(0), Type = Event.EventType.Vacation }); //green
}
}
if (sessiondata.Completed == false)
{
if (sessionExercise.FinishedAt == calArg.Past)
{
List<Event> events = new List<Event>();
events.Add(new Event() { Title = "Exercises Uncompleted", EventDate = DateTime.Now.AddDays(0), Type = Event.EventType.Critical }); //red
}
}
}
_db.SaveChanges();
return RedirectToAction("CalendarIndex"); // or where ever you want to go
}
else
{
return View(calArg);
}
}
public class Event
{
public string Title
{
get;
set;
}
public DateTime EventDate
{
get;
set;
}
public EventType Type
{
get;
set;
}
public enum EventType
{
Appointment,
Meeting,
Vacation,
Birthday,
Personal,
Critical
}
}
Model.Calendar.cs
public class Calendar
{
int _year;
int _month;
DateTime _selectedDate;
string _viewFile = "";
ViewDataDictionary _viewData = new ViewDataDictionary();
Func<DateTime, bool, string> _onDayRenderFunc = null;
public Calendar()
{
SetDate(DateTime.Now.Year, DateTime.Now.Month);
}
public void SetDate(int year, int month)
{
_year = year;
_month = month;
_selectedDate = new DateTime(_year, _month, 1);
}
public void SetDate(int year, int month, int day)
{
_year = year;
_month = month;
_selectedDate = new DateTime(_year, _month, day);
}
public DateTime Date
{
get
{
return _selectedDate;
}
}
public void OnDayRender(Func<DateTime, bool, string> func)
{
_onDayRenderFunc = func;
}
public void View(string viewFile)
{
_viewFile = viewFile;
}
public ViewDataDictionary ViewData
{
get
{
return _viewData;
}
}
public string Render()
{
string[] dayNames = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
int daysInMonth = DateTime.DaysInMonth(_year, _month);
int pYear = _year;
int pMonth = _month;
if ((_month - 1) < 1)
{
--pYear;
pMonth = 12;
}
else
{
--pMonth;
}
int daysInPrevMonth = DateTime.DaysInMonth(pYear, pMonth);
DateTime d1 = new DateTime(_year, _month, 1);
int dayPos = (int)d1.DayOfWeek;
daysInPrevMonth -= dayPos - 1;
StringBuilder control = new StringBuilder();
control.Append("<table cellpadding=\"0\" cellspacing=\"0\">\n<thead>\n<tr>\n");
for (int i = 0; i < dayNames.Length; i++)
{
control.Append(string.Format("<th>{0}</th>\n", dayNames[i]));
}
control.Append("</thead>\n<tbody>\n");
int totalDaysInMonth = daysInMonth + dayPos;
int col = 0;
int day = 0;
string cellValue = "";
for (int idx = 0; idx < totalDaysInMonth; idx++)
{
if (col == 0)
{
control.Append("<tr>\n");
}
if (idx >= dayPos)
{
++day;
if (_viewFile == "")
{
cellValue = _onDayRenderFunc != null ? _onDayRenderFunc(new DateTime(_year, _month, day), true) : day.ToString();
}
else
{
ViewData.Model = new CalendarArg() { Date = new DateTime(_year, _month, day), SelectedDate = _selectedDate, CurrentMonth = true };
cellValue = this.Parse(_viewFile);
}
control.Append(string.Format("<td data-day=\"{0}\" data-month=\"{1}\" data-year=\"{2}\">{3}</td>\n", day, _month, _year, cellValue));
}
else
{
if (_viewFile == "")
{
cellValue = _onDayRenderFunc != null ? _onDayRenderFunc(new DateTime(pYear, pMonth, daysInPrevMonth), false) : daysInPrevMonth.ToString();
}
else
{
ViewData.Model = new CalendarArg() { Date = new DateTime(pYear, pMonth, daysInPrevMonth), SelectedDate = _selectedDate, CurrentMonth = false };
cellValue = this.Parse(_viewFile);
}
control.Append(string.Format("<td>{0}</td>\n", cellValue));
++daysInPrevMonth;
}
if (col == 6)
{
control.Append("</tr>\n");
col = 0;
continue;
}
++col;
}
if (col < 7)
{
int nextMonthDay = 1;
for (int c = col; c < 7; c++)
{
if ((_month + 1) > 12)
{
++_year;
_month = 1;
}
else
{
++_month;
}
if (_viewFile == "")
{
cellValue = _onDayRenderFunc != null ? _onDayRenderFunc(new DateTime(_year, _month, nextMonthDay), false) : nextMonthDay.ToString();
}
else
{
ViewData.Model = new CalendarArg() { Date = new DateTime(_year, _month, nextMonthDay), SelectedDate = _selectedDate, CurrentMonth = false };
cellValue = this.Parse(_viewFile);
}
control.Append(string.Format("<td>{0}</td>\n", cellValue));
++nextMonthDay;
}
control.Append("</tr>\n");
}
control.Append("</tbody>\n</table>\n");
return control.ToString();
}
private string Parse(string viewFile)
{
using (var sw = new StringWriter())
{
ControllerContext ctx = new System.Web.Mvc.ControllerContext();
ctx.HttpContext = new HttpContextWrapper(HttpContext.Current);
RazorView view = new RazorView(ctx, viewFile, "", false, null);
TempDataDictionary tdd = new TempDataDictionary();
var viewContext = new ViewContext(ctx, view, ViewData, tdd, sw);
view.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
}
Model.CalendarArg.cs
public class CalendarArg
{
public DateTime SelectedDate { get; set; }
public DateTime Date { get; set; }
public bool CurrentMonth { get; set; }
public bool CompletionRequested { get; set; }
public DateTime CompletedToday { get; set; }
}
View.CalendarIndex.cshtml
<style>
table {
width: 100%;
border: 0px;
border-collapse: collapse;
border: 1px solid #EEE;
}
table thead tr th {
font-family: Tahoma;
font-weight: normal;
color: #666;
}
table tbody tr td {
border: 1px solid #EEE;
width: 14%;
}
table tbody tr td .cell1, .cell2 {
min-height: 150px;
height: 100%;
}
table tbody tr td .selected_day h2 {
Color: #FFF;
background-color: #3498DB;
text-shadow: none;
}
table tbody tr td .cell1 {
background-color: #FFF;
}
table tbody tr td .cell1:hover h2 {
box-shadow: 1px 2px 3px #999;
}
table tbody tr td .cell2 {
background-color: #FCFCFC;
}
table tbody tr td .cell2 h2 {
color: #CCC;
}
table tbody tr td h2 {
font-family: Tahoma;
font-size: 20px;
font-weight: normal;
float: right;
margin: 0px;
padding: 6px;
color: #154B67;
background-color: #EEE;
display: block;
width: 25px;
height: 25px;
text-align: center;
text-shadow: 2px 1px #FFF;
}
table tbody tr td .evt {
font-family: Tahoma;
font-size: 12px;
margin: 5px;
padding: 10px;
color: #FFF;
border-radius: 2px;
}
table tbody tr td .clear {
clear: both;
}
.Meeting {
background-color: #DDD;
color: #222 !important;
}
.Personal {
background-color: #3498DB;
}
.Vacation {
background-color: #2ECC71;
}
.Appointment {
background-color: #F5AB35;
}
.Critical {
background-color: #F22613;
}
</style>#Html.Raw(ViewBag.calendar)
View.Calendar.cshtml
#model Project.Models.CalendarArg
#{
CalendarArg calArg = this.Model;
List<Project.Controllers.Event> events = (List<Project.Controllers.Event>)ViewData["events"];
string cssClass = calArg.CurrentMonth == true ? "cell1" : "cell2";
}
#if (calArg.Date.Day == calArg.SelectedDate.Day)
{
cssClass += " selected_day";
}
#if (calArg.Date.Day == calArg.Date.Day)
{
if (DateTime.Now <= calArg.Date)
{
#Html.CheckBoxFor(m => m.CompletionRequested, new { #checked = calArg.CompletionRequested });
}
}
<div class="#cssClass">
<h2>#calArg.Date.Day.ToString()</h2>
<div class="clear"></div>
#foreach (var evt in events)
{
if (evt.EventDate.Date.ToString("yyyyMMdd") == calArg.Date.ToString("yyyyMMdd"))
{
<div class="evt #evt.Type.ToString()">#evt.Title</div>
}
}
</div>
UPDATE
By adding this line of code to Calendar.cshtl:
#if (calArg.Date.Day == calArg.Date.Day)
{
#Html.CheckBoxFor(m => m.CompletionRequested, new { #checked = calArg.CompletionRequested });
}
It surprisingly works, so i guess i'd like to know how to alter the css style sheet in calendar index to have the checkboxes flush with the calendar design (i.e. inline with the calendar and not just above it) and how to save changes to the bool to the db.
Have this inside the foreach loop:
#Html.CheckBoxFor(m => m.CompletionRequested , new { #checked = evt.CompletionRequested });
UPDATE:
Answer to your question in comments. Do HttpPost to controller and pass model data.
[HttpPost]
public ActionResult CalendarIndex(CalendarArg model)
{
// Check that model is valid
if(ModelState.IsValid)
{
// CODE here to update Database
return RedirectToAction("Index"); // or where ever you want to go
}
else
{
return View(model); // Return back to View, model is not valid
}
}
UPDATE 2:
If you want to add a class name you can do it like this:
#Html.CheckBoxFor(m => m.CompletionRequested , new { #checked = evt.CompletionRequested, #class = "checkbox" });
Or you can add css like this:
input[type="radio"]:checked
{
// css when radio button is selected
}
input[type="radio"]
{
// css when radio button is not selected
}
These CSS styles is global so every input element with type radio will get styles.
And when you want to change changes to db context, you need first find the current one from context. Then add true value to CompletionRequested property and then call SaveChanged method from your context. You'r first question was to get checkboxes on your calendarView, not how to save changes to db. That's another question.
Related
I'm trying to Implement ExportToPDF() action method in my MCV.CORE web app.
Now obviously in my EmployeeCategory class I have different data types(int,string,double).
So, my conclusion why I'm getting error, is because data type needs to be only string type. Which is not possible in my case.
I'm not sure how to correctly implement this action method.
Errors that I'm getting is:
Cannot convert type Test_Project_Web.Models.EmployeeCategory to string[]
No best type found for implicitly-typed array
My simplified code:
EmployeeCategory.cs :
public class EmployeeCategory
{
[Key]
public int Id { get; set; }
[Required]
public string? Name { get; set; }
[Required]
public string? LastName { get; set; }
[Required]
public string? Address { get; set; }
[Required]
public double NetSalary { get; set; }
[Required]
public double GrossSalary { get; set; }
}
EmployeeCategoryController.cs :
private ApplicationDbContext Context { get; }
public EmployeeCategoryController(ApplicationDbContext _context)
{
Context = _context;
}
public IActionResult Index()
{
return View(this.Context.EmployeeCategories.Take(6).ToList());
}
[HttpPost]
public FileResult ExportToPDF()
{
List<EmployeeCategory> employees = (from employee in Context.EmployeeCategories.Take(6)
select new[] {
employee.Id,
employee.Name,
employee.LastName,
employee.Address,
employee.NetSalary,
employee.GrossSalary
}).ToList<EmployeeCategory>();
//Building an HTML string.
StringBuilder sb = new StringBuilder();
//Table start.
sb.Append("<table border='1' cellpadding='5' cellspacing='0' style='border: 1px solid #ccc;font-family: Arial; font-size: 10pt;'>");
//Building the Header row.
sb.Append("<tr>");
sb.Append("<th style='background-color: #B8DBFD;border: 1px solid #ccc'>Id</th>");
sb.Append("<th style='background-color: #B8DBFD;border: 1px solid #ccc'>Name</th>");
sb.Append("<th style='background-color: #B8DBFD;border: 1px solid #ccc'>LastName</th>");
sb.Append("<th style='background-color: #B8DBFD;border: 1px solid #ccc'>Address</th>");
sb.Append("<th style='background-color: #B8DBFD;border: 1px solid #ccc'>NetSalary</th>");
sb.Append("<th style='background-color: #B8DBFD;border: 1px solid #ccc'>GrossSalary</th>");
sb.Append("</tr>");
//Building the Data rows.
for (int i = 0; i < employees.Count; i++)
{
string[] employee = (string[])employees[i];
sb.Append("<tr>");
for (int j = 0; j < employee.Length; j++)
{
//Append data.
sb.Append("<td style='border: 1px solid #ccc'>");
sb.Append(employee[j]);
sb.Append("</td>");
}
sb.Append("</tr>");
}
//Table end.
sb.Append("</table>");
using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(sb.ToString())))
{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(byteArrayOutputStream);
PdfDocument pdfDocument = new PdfDocument(writer);
pdfDocument.SetDefaultPageSize(PageSize.A4);
HtmlConverter.ConvertToPdf(stream, pdfDocument);
pdfDocument.Close();
return File(byteArrayOutputStream.ToArray(), "application/pdf", "EmployeeList.pdf");
}
}
I don't think this error has anything to do with the data types of your Employee properties and has more to do with you trying to cast an Employee to a string[]:
string[] employee = (string[])employees[i];
Aside from this not being possible (using the method above) I don't think it is necessary as you can obtain the properties and their values to output them as it appears you're attempting to do in your question.
employees.ForEach(employee =>
{
sb.Append("<tr>");
foreach (var propertyInfo in employee.GetType().GetProperties())
{
sb.Append("<td style='border: 1px solid #ccc'>");
sb.Append(propertyInfo.GetValue(employee));
sb.Append("</td>");
}
sb.Append("</tr>");
});
What's the Blazor equivalent of this Knockout.js data-binding?
I can easily create a foreach loop through a C# List<T> object and bind to the object's properties however I'm struggling with this as the binding is for the id attributes.
HTML code:
<div data-bind="foreach : combinedArr">
<div data-bind="with: $data.recordCo">
<table id="tableFull">
<tbody>
<tr>
<td class="fixed-width iconCol" data-bind="with: $parent.targetCo">
<button data-bind="attr: { 'data-target': $data[0].tableTargetID, id: $data[0].buttonID }" data-toggle="collapse" type="button" onclick="glyphChanger(this.id)" class="btn btn-default iconButton glyphicon glyphicon-chevron-right" aria-label="Left Align" aria-hidden="true"></button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="tbAdj panel panel-collapse collapse" data-bind="attr: { id: $data.countCo }">
<table class="table table-condensed tableSize tableSpacer" id="tableFull">
<tbody data-bind="foreach: $data.jsonCo">
....
</tbody>
</table>
</div>
</div>
Javascript code:
self.combinedArr = ko.observableArray();
self.post = function () {
voidNotification = false;
self.combinedArr.removeAll();
$.post(this.api + "/tabular", {
value: this.logSource()
}).success(
function (d) {
var counter = 0;
$.each(d, function (i, o) {
var objArr = JSON.parse(o);
//Parse a second time to access the objects individually
var recordParsed = JSON.parse(objArr[0]);
var jsonParsed = JSON.parse(objArr[1]);
//Data to populate the expandable table
jsArr = [];
for (var x in jsonParsed) {
jsArr.push({ jfieldName: jsonParsed[x].Name, jfieldValue: jsonParsed[x].Value });
}
//ID for the button that expands and collapses the table
var buttonID = "btUniqID" + counter;
//The id of the table - needs to be in the same array as the buttonID
var tableTargetID = "#jsonTable" + counter;
var idArr = [];
idArr.push({ tableTargetID: tableTargetID, buttonID: buttonID });
//The id for that table that needs to be on its own
var uniqueTableID = "jsonTable" + counter;
//Combine all the data and push to the combinedArr
self.combinedArr.push({ recordCo: recordParsed, jsonCo: jsArr, countCo: uniqueTableID, targetCo: idArr });
//Incremented for unique button ids
counter++;
});
if (counter === 0) {
self.FaultFound(true);
self.FaultText("Data could not be parsed");
$("#recordTable").css("display", "none");
} else {
self.FaultFound(false);
//Check if transaction is void
VoidHandler();
//Hides the loading animation
self.ShowDetailsLoading(false);
//Show the recordsTable
$("#recordTable").css("display", "block");
}
})
.error(
function (d) {
alert('failed ' + d);
}
);
}
I've created a C# class equivalent to self.combinedArr with the rows variable below:
public List<CombinedRow> rows = new List<CombinedRow>();
private async Task OnParseClicked()
{
try
{
var response = await Http.PostAsJsonAsync("api/TLogParser/Records", new TLogMessageRequestDto(logMessage: inputMessage));
parsedMessage = await response.Content.ReadFromJsonAsync<IEnumerable<RecordItem>>();
var jsArray = new List<Record>();
foreach (var m in parsedMessage)
{
jsArray.Add(new Record { jfieldName = m.MessageId, jfieldValue = m.RecordBody });
}
var counter = 0;
foreach (var m in parsedMessage)
{
//ID for the button that expands and collapses the table
var buttonID = "btUniqID" + counter;
//The id of the table - needs to be in the same array as the buttonID
var tableTargetID = "#jsonTable" + counter;
var row = new Row() { ButtonId = buttonID, TableTargetId = tableTargetID };
//The id for that table that needs to be on its own
var uniqueTableID = "jsonTable" + counter;
var combinedRow = new CombinedRow { recordCo = m, JsonCo = jsArray, CountCo = uniqueTableID, TargetCo = row};
rows.Add(combinedRow);
counter++;
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public class CombinedRow
{
public RecordItem recordCo { get; set; }
public Row TargetCo { get; set; }
public string CountCo { get; set; }
public List<Record> JsonCo { get; set; }
}
public class Row
{
public string ButtonId { get; set; }
public string TableTargetId { get; set; }
}
public class Record
{
public string jfieldName { get; set; }
public string jfieldValue { get; set; }
}
However, I'm not sure on the HTML/Blazor binding part of how to bind to the id attributes.
I currently have this loop:
if (lists.Date.Count() == 0)
{
message = "There Have Been No Merged Pull Requests In This Repository";
}
else
{
for (int i = 0; i < lists.Date.Count(); i++)
PullRequests = new List<PullRequestDetails>
{
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[i],
Name = lists.Name[i],
Date = lists.Date[i],
CommitLink = lists.ShortCommitList[i],
},
};
}
which takes strings from lists and sets them in this model:
public class PullRequestDetails
{
public string? Title { get; set; }
public string? Name { get; set; }
public string? Date { get; set; }
public string? CommitLink { get; set; }
}
I want my HTML to display every item from the list when the button is clicked, but currently it is only displaying the last item from the list:
#if (Model.PullRequests != null)
{
#foreach (var requests in Model.PullRequests)
{
<tbody>
<tr>
<td>#requests.Title</td>
<td>#requests.Name</td>
<td>#requests.Date</td>
<td> Link </td>
</tr>
</tbody>
}
}
This works when I manually add each value of the list, but his gives an out of range exception when there are less or more than 4 values in each list (which there are in most cases):
if (lists.Date.Count() == 0)
{
html = "There Have Been No Merged Pull Requests In This Repository";
}
else
{
for (int i = 0; i < lists.Date.Count(); i++)
PullRequests = new List<PullRequestDetails>
{
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[0],
Name = lists.Name[0],
Date = lists.Date[0],
CommitLink = lists.ShortCommitList[0]
},
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[1],
Name = lists.Name[1],
Date = lists.Date[1],
CommitLink = lists.ShortCommitList[1]
},
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[2],
Name = lists.Name[2],
Date = lists.Date[2],
CommitLink = lists.ShortCommitList[2]
},
new PullRequestDetails()
{
Title = lists.ShortRequestTitle[3],
Name = lists.Name[3],
Date = lists.Date[3],
CommitLink = lists.ShortCommitList[3]
},
};
}
So how can I fix this with a loop?
Just as #Camilo Terevinto said you need too take the List instantiation out of the loop
if (lists.Date.Count() == 0)
{
message = "There Have Been No Merged Pull Requests In This Repository";
}
else
{
PullRequests = new List<PullRequestDetails>();
for (int i = 0; i < lists.Date.Count(); i++)
{
PullRequests.Add(new PullRequestDetails()
{
Title = lists.ShortRequestTitle[i],
Name = lists.Name[i],
Date = lists.Date[i],
CommitLink = lists.ShortCommitList[i]
});
};
}
I am wondering if I can sum up decimal in all the columns that are dynamically generated in razor view without having to change this in controller and viewModel. I will be happy to try jQuery option as well.
ViewModel
public class LedgerViewModel
{
public LedgerViewModel(int PayCategoryCount)
{
PayCollection = new List<decimal>(new decimal[PayCategoryCount]);
}
public DateTime PDate { get; set; }
public class MonthlyPaymentsVM
{ public int PayCategoryId { get; set; }
[DisplayFormat(DataFormatString = "{0:MMMM yyyy}")]
public DateTime Date { get; set; }
public IEnumerable<string> PaymentCategories { get; set; }
public List<LedgerViewModel> Payments { get; set; }
public List<LedgerViewModel> Member { get; set; }
}
controller
public ActionResult Report(int year, int no, string nom, Guid gcode)
{
DateTime startdate = (new DateTime(DateTime.Now.Year - 1, 7, 1));
DateTime enddate = (new DateTime(DateTime.Now.Year, 7, 1));
DateTime date = DateTime.Now;
//get all payments
var a = from of in db.OfflinePayMents.Include(i => i.Customer).Include(i => i.PaymentCategory).ToList().Where(x => x.PDate >= startdate && x.PDate < enddate && x.POK && x.CustomerGuid=gcode) select new { of.Customer, of.PaymentCategory, of.CustomerID, of.PaymentCategoryID, of.PDate, of.TxnId, of.Pay, of.PType };
var grouped = a.GroupBy(x => new { customer = x.CustomerID, PaymentCategory = x.PaymentCategory.PaymentCategoryID, txn = x.TxnId, pd = x.PDate, x.PType }).Select(x => new
{
Name = x.First().Customer.Name,
Customer = x.First().Customer,
PaymentCategory = x.First().PaymentCategory,
Txn = x.First().TxnId,
Pd = x.First().PDate,
PType = x.First().PType,
cid = x.First().PaymentCategoryID,
Pay= x.Sum(y => y.Pay)
});
var data = grouped.GroupBy(x => x.Txn);
var PaymentCategories = db.PaymentCategories.OrderBy(z => z.Order);
var PayCategoryCount = PaymentCategories.Count();
var PaymentCategoryIDs = PaymentCategories.Select(x => x.PaymentCategoryID).ToList();
var model = new MonthlyPaymentsVM()
{
//Member = members,
Date = date,
PaymentCategories = PaymentCategories.Select(z => z.PaymentCategoryTitle),
Payments = new List<LedgerViewModel>()
};
foreach (var group in data)
{
LedgerViewModel payment = new LedgerViewModel(PaymentCategoryCount);
var pd = group.First().Pd;
payment.PDate = pd;
foreach (var item in group)
{
int index = PaymentCategoryIDs.IndexOf(item.PaymentCategory.PaymentCategoryID);
if (index < 0)
{
payment.PayCollection[index + 1] = item.Pay;
}
else
{
payment.PayCollection[index] = item.Pay;
}
payment.Total += item.Pay;
}
model.Payments.Add(payment);
}
return View(model);
}
Razor View
<table class="doubleborder" width="99%" border="0" align="center" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>Date</th>
#foreach (var payname in Model.PaymentCategories)
{
<th>#payname</th>
}
</tr>
</thead>
<tbody>
#foreach (var item in Model.Payments)
{
<tr>
<td>#item.PayDate.ToString("dd/MM/yyyy")</td>
#foreach (var amount in item.PayCollection)
{
<td>#amount.ToString("c")</td>
}
</tr>
}
<tr class="doubleborder">
<td>Total:</td>
#foreach (var item in Model.PaymentCategories)
{
<td>
looking at getting sum totals of each column here
</td>
}
</tr>
</tbody>
</table>
So this groups by customer. The payments are grouped by transaction Date and are iterated in the foreach loop in the view.
Thanks if you are able to help.
If I understand your model correctly, this is what you are looking for:
#Model.Payments.Sum(i => i.Paycollection.Sum(x => x.amount));
Update, based on your comment: (and assuming that all the columns have value for all the PaymentCollections)
#for(int i = 0 ; i < PaymentCategories.Count(); i++)
{
<td>
Model.Payments.Sum(x => x.PayCollection[i]); //this will throw an exception if the value at index is not defined
</td>
}
I want to create a custom grid which will have three columns and rows can be of any number that depends on the data. But my problem is the data is available as json. I have created grid like structure many times but that is with model and collections like:
First creating the divs for columns
#{
if (Model.MessageList.Count > 0)
{
<div class="GridView_Div">
<div class="GridHeader_Div">
<div class="GridHeaderColoums_Div">Message</div>
<div class="GridHeaderColoums_Div">Sent Date</div>
<div class="GridHeaderColoums_Div">Receive Date</div>
<div class="GridHeaderColoums_Div">Actions</div>
</div>
<div class="GridData_Div">
#{
for (int i = 0; i < Model.MessageList.Count; i++)
{
string resultMessage = string.Empty;
string newMessage = string.Empty;
string result1 = Model.MessageList.ElementAt(i).Message;
int length = result1.Length;
if (length > 5)
{
resultMessage = result1.Substring(0, 5);
newMessage = resultMessage + "......";
}
else
{
resultMessage = result1.Substring(0);
newMessage = resultMessage + "......";
}
<div class="Grid_Row">
<div class="GridData_Coloums">
#newMessage
</div>
<div class="GridData_Coloums">#Model.MessageList.ElementAt(i).Sent_Date</div>
<div class="GridData_Coloums"> #Model.MessageList.ElementAt(i).Receive_Date</div>
<div class="GridData_Coloums">
<input type="button" value="Delete" id="#Model.MessageList.ElementAt(i).pkMessageId"/>
</div>
</div>
}
}
</div>
</div>
}
else
{
<div style="width: 50%; float: left; margin-left: 10%;">No Message Found</div>
}
}
But how can I create a grid like structure in Json data?
Please help me with this case. Thank you very much
This has been a challenge for me and I accomplished it.
In the view
$(document).ready(function () {
$("#hdnPkClientId").val('');
$("#txt_Autocomplete").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Home/SearchClientDetail",
data: "{'searchtext':'" + document.getElementById('txt_Autocomplete').value + "'}",
dataType: "json",
success: function (data) {
response($.map(data.Data, function (item) {
return {
label: item.Name,
value: item.id,
data: item
};
}));
},
error: function (xhr)
{ }
});
},
select: function (event, ui) {
var detailArr = ui.item.label.split(',');
$("#txt_Autocomplete").val(detailArr[0]);
$("#hdnPkClientId").val(ui.item.data.Id);
$("#Evaluation_Anch").attr("href", "/Evaluation/Index?Client_ID=" + ui.item.data.Id);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/ClientHome/GetSelectedClientDetails",
data: "{'ClientId':'" + document.getElementById('hdnPkClientId').value + "'}",
dataType: "json",
success: function (data) {
$("#Client_Name").html(data.Info.Name);
$("#Client_Address").html(data.Info.Address);
$("#Client_OtherAddressDetails").html(data.Info.OtherAddressDetails);
$("#Client_DOB").html(data.Info.DOB);
$("#Client_Phone").html(data.Info.Phone);
$("Client_MobilePhone").html(data.Info.Mobile_Phone);
var DataDiv = "<table width='100' border='0' cellspacing='0' cellpadding='0'> <tr> <th class='head'>Date</th> <th class='head'>Document Type</th> <th class='head'>Provider</th> </tr>";
for (var iRow = 0; iRow < data.Info.Prev_Doc_List.length; iRow++) {
var temp = data.Info.Prev_Doc_List[iRow];
DataDiv += "<tr>";
DataDiv += "<td>" + temp.Created_Date + "</td>";
DataDiv += "<td><a id='" + temp.Page_ID + "' href='" + temp.RedirectAddress + "'>" + temp.Doc_type + "</a></td>";
DataDiv += "<td>" + temp.Provider + "</td>";
DataDiv += "</tr>";
}
DataDiv += "</table>";
$("#PreviousDocumentDiv").html(DataDiv);
},
error: function (xhr)
{ }
});
return false;
}
});
});
In controller
[HttpPost]
public ActionResult GetSelectedClientDetails(string ClientId)
{
ProgressNotesService objService = new ProgressNotesService();
var Client_Detail = objService.GetSelectedClient(Convert.ToInt32(ClientId));
if (Client_Detail != null)
{
Session["Client_ID"] = Client_Detail.Id;
}
return Json(new { Info = Client_Detail });
}
In Service
public ClientDetailModel GetSelectedClient(int ClientID)
{
ClientDetailModel ClientDetail = new ClientDetailModel();
List<PreviousDocuments> objDocsList = new List<PreviousDocuments>();
using (DataContext DB = new DataContext())
{
var Row = DB.tbl.Where(m => m.ID == ClientID).FirstOrDefault();
if (Row != null)
{
ClientDetail.Id = Row.ID.ToString();
ClientDetail.Name = Row.First_Name + " " + Row.Last_Name;
ClientDetail.Address = Row.Address;
ClientDetail.Client_DOB = (DateTime)Row.DOB;
ClientDetail.DOB = ClientDetail.Client_DOB.ToString("MM/dd/yyyy");
ClientDetail.OtherAddressDetails = (Row.City == "" || Row.City == null ? "N/A" + " " + "," : Row.City + " ,") + (Row.State == "" || Row.State == null ? "N/A" + " " + "," : Row.State + " ,") + (Row.ZipCode == "" || Row.ZipCode == null ? "N/A" : Row.ZipCode);
ClientDetail.Phone = Row.Phone;
ClientDetail.Mobile_Phone = Row.OtherContact_Phone;
var ProgressNoteRecords = DB.ProgressNotes.Where(m => m.FkReferralID == ClientID).ToList();
if (ProgressNoteRecords.Count() > 0)
{
for (int iRow = 0; iRow < ProgressNoteRecords.Count(); iRow++)
{
objDocsList.Add(new PreviousDocuments
{
Created_Date = Convert.ToString(ProgressNoteRecords.ElementAt(iRow).Created_Date),
Doc_type = "Progress Note",
Provider = " blah blah",
Page_ID = Convert.ToString(ProgressNoteRecords.ElementAt(iRow).Id),
RedirectAddress = "../ProgressNote/Add?ProgressNote_ID=" + Convert.ToString(ProgressNoteRecords.ElementAt(iRow).Id)
});
}
}
var Ref = DB.tblrefServices.Where(m => m.ID == ClientID).ToList();
if (Ref.Count > 0)
{
for (int iRow = 0; iRow < Ref.Count(); iRow++)
{
objDocsList.Add(new PreviousDocuments
{
Created_Date = Convert.ToString(Ref.ElementAt(iRow).First_Name),
Doc_type = "Referral Service",
Provider = "blah blah",
Page_ID = Convert.ToString(Ref.ElementAt(iRow).ID)
});
}
}
ClientDetail.Prev_Doc_List = objDocsList;
}
}
return ClientDetail;
}
In model
public class ClientDetailModel
{
public ClientDetailModel()
{
Prev_Doc_List = new List<PreviousDocuments>();
}
public string Name { get; set; }
public string Id { get; set; }
public string DOB { get; set; }
public string Address { get; set; }
public string OtherAddressDetails { get; set; }
public string Phone { get; set; }
public string Mobile_Phone { get; set; }
public DateTime Client_DOB { get; set; }
public List<PreviousDocuments> Prev_Doc_List { get; set; }
}
public class PreviousDocuments
{
public string Created_Date { get; set; }
public string Doc_type { get; set; }
public string Provider { get; set; }
public string Page_ID { get; set; }
public string RedirectAddress { get; set; }
}
You can use KnockoutJS to bind your json data to your custom grid
what about using any template engines like jsrender. where you can convert provided mvc's view code to templates. Then pass the json to the template that will render grid in desired element.
refer the below link for more details
http://borismoore.github.io/jsrender/demos/demos.html
http://www.jsviews.com/#jsrender