Get HTML check box to toggle MVC model boolean - c#

I am trying to use an MVC form to modify some information in my database. I want to be able to select a few items from a table using a series check boxes. It should update the database boolean values when I hit a link at the bottom of my form.
So far, I have tried a few solutions from other threads, but since I am new to MVCs, they are rather confusing.
This is what I have right now for my HTML:
#foreach (var item in Model)
{
<tr>
#if (!item.IsCurated)
{
<td>
#Html.CheckBoxFor(modelItem => item.isChecked, new { #checked = true })
</td>
{
</tr>
#Html.ActionLink("Update", "updateDatabase", Model)
The "updateDatabase" method calls
public void updateDatabase()
{
db.SaveChanges();
}
I believe the changes to the database are being saved, but that the check boxes are not actually assigning any changed values.

Related

ASP.NET Blazor uncheck all checkboxes in foreach loop with function

My Problem is that i have a list of checkboxes which are generated by a foreach loop.
How can i uncheck all the checkboxes with one function. Here is my code:
<tbody>
#foreach (var mandant in supportUserResult)
{
<tr>
<td><input type="checkbox" #onchange="eventArgs => { AddChosenSupportUserToList(mandant, eventArgs.Value); }" /></td>
<td>#(mandant.Scope)</td>
<td>#(mandant.Name)</td>
<td>#(usercategory)</td>
<td>#(mandant.FullName)</td>
<td>#(mandant.MailAddress)</td>
<td>#(mandant.Language)</td>
</tr>
}
</tbody>
I know how i can uncheck one with the #bind value, but ist not clear for me how to do that with all the generated checkboxes. And its important, that checkbox call the function 'AddChosenSupportUSerToList'.
What you're doing now is triggering an event when the checkbox is fired, without saving the state of your checkbox in your code.
You want to bind the actual state to a property. Once you've done so, you can then create a button to 'reset' each checkbox to the default state (this is how I interpret your desired behavior).
This post shows how to bind the state for one checkbox. For your purposes, you incorporate in your supportUserResult loop:
2 useful examples;
Blazor Checkbox two-way binding and change event
Blazor - Create select box dynamically
Using that example, you get something like this:
#for (int i = 0; i < supportUserResult.Count(); i++)
{
var mandant = supportUserResult[i];
<tr>
<td><input type="checkbox" #onchange="eventArgs => { ValueHasChanged(i, mandant, eventArgs.Value); }" /></td>
<td>#(mandant.Scope)</td>
<td>#(mandant.Name)</td>
<td>#(usercategory)</td>
<td>#(mandant.FullName)</td>
<td>#(mandant.MailAddress)</td>
<td>#(mandant.Language)</td>
</tr>
}
#code {
// this is your view model
var checkBoxValues = new List<bool>();
// this method will add a new item to the collection of select boxes
void ValueHasChanged(int i, Mandant mandant, eventArgs.Value )
{
if (eventArgs.Value) {
AddChosenSupportUserToList(mandant, eventArgs.Value)
}
checkBoxValues[i] = eventArgs.Value;
}
}
I'm not in a position to test the above for errors but this should help you.

ASP.NET-MVC - Website running total function not working

Trying to create a running total that will count calories for my website as part of a college assignment. Everything is finished apart from this one section which keeps on tripping me up. In theory it should take in a value and add it to a running total and display this total, but I think each time I press the button to calculate this it runs a new instance of the model I use to calculate this. There are 3 files interacting with each other for this operation
CalorieCount.cs - The model which contains the data and the calculation
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace BlairMackenzie_CalorieCount.Models
{
public class CalorieCount
{
// Stores user input for calculating calorie count
[Required]
[Display(Name = "Calories Consumed")]
public int CalorieIntake { get; set; }
// Stores the running total
[Display(Name = "Total Calories Consumed Today")]
public int TotalCalorieCount { get; set; }
// This method calculates total calorie count
public void CalculateTotalCalorieCount()
{
// Add CalorieIntake to TotalCalorieCount
TotalCalorieCount += CalorieIntake;
}
}
}
CalorieCounter.cshtml - The webpage to display all this to the user and take an input
#{
ViewBag.Title = "CalorieCounter";
}
<h2>Calorie Counter</h2>
<br />
<hr />
#using (Html.BeginForm())
{
<div class="table-responsive">
<table class="table table-lg">
<tr>
<!-- Displays label and input box for CalorieIntake -->
<td>#Html.LabelFor(m => m.CalorieIntake)</td>
<td>#Html.EditorFor(m => m.CalorieIntake)</td>
</tr>
<tr>
<!-- Displays label and display for TotalCalorieCount -->
<td>#Html.LabelFor(m => m.TotalCalorieCount)</td>
<td>#Html.DisplayFor(m => m.TotalCalorieCount)</td>
</tr>
<tr>
<td></td>
<td>
<!-- Submit button triggers calculation -->
<input type="submit" value="Calculate New Total Calories" class="btn btn-lg btn-success" />
</td>
</tr>
</table>
</div>
}
HomeController.cs - handles the loading the page and calling for the model to handle the calculations
// Loads Calorie Count Page
// Sets up empty form
[HttpGet]
public ActionResult CalorieCounter()
{
return View();
}
// This action is called when the user clicks the submit button
// The completed form is sent to the back end
[HttpPost]
public ActionResult CalorieCounter(CalorieCount model)
{
if (ModelState.IsValid)
{
model.CalculateTotalCalorieCount();
}
return View(model); // Return the model to the view with all values calculated
}
If anyone can spot this issue and suggest a fix that would be great thanks.
There's some fundamental misunderstandings going on here. ASP.NET MVC is essentially a "stateless" system. So when you make a request from the browser to the server, everything on the server is brand-new, uninitialised memory. It's "newing-up" all objects that are used to process the request and send a response.
So if you have a bit of data that you want to persist between requests, you have a couple of options:
Make sure all the data you need is "round-tripped" each time. That will often mean you need hidden <input /> fields in your pages to contain that data, inside the form. As long as those inputs are setup correctly (I recommend using HtmlHelper, i.e. Html.HiddenFor<T>()) then the framework will match the value up and set that property of the model object in your POST handler.
Store data on the server, in a database. each request loads the current data, adds the new amount to it, and saves it, then displays whatever it needs to on the page.
UPDATE
After making a working MVC site from your example and replicating the problem, I did some research and found that the HtmlHelpers look at ModelState before looking at the model that was passed to the view. This is why the value is never updating. I also noticed that there was a validation error because the int TotalCalorieCount implied a value was required, and presumably 0 wasn't good enough.
So here's what I did to get it working:
Add #Html.HiddenFor(m => m.TotalCalorieCount) immediately before the submit button in the view.
Make CalorieCount.TotalCalorieCount int? rather than int (which removed the DataAnnotations-implied requirement to be present.
Added a call to ModelState.Clear() immediately inside the if (ModelState.IsValid) block in HomeController.
It now works as you'd expect for me.
HomeController.cs
// Loads Calorie Count Page
// Sets up empty form
[HttpGet]
public ActionResult CalorieCounter()
{
return View();
}
// This action is called when the user clicks the submit button
// The completed form is sent to the back end
[HttpPost]
public ActionResult CalorieCounter(CalorieCount model)
{
if (ModelState.IsValid)
{
ModelState.Clear();
model.CalculateTotalCalorieCount();
}
return View(model); // Return the model to the view with all values calculated
}
CalorieCount.cs
using System.ComponentModel.DataAnnotations;
namespace WebApplication1.Models
{
public class CalorieCount
{
// Stores user input for calculating calorie count
[Required]
[Display(Name = "Calories Consumed")]
public int CalorieIntake { get; set; }
// Stores the running total
[Display(Name = "Total Calories Consumed Today")]
public int? TotalCalorieCount { get; set; }
// This method calculates total calorie count
public void CalculateTotalCalorieCount()
{
// Add CalorieIntake to TotalCalorieCount
TotalCalorieCount = (TotalCalorieCount ?? 0) + CalorieIntake;
}
}
}
CalorieCounter.cshtml
#model CalorieCount
#{
ViewBag.Title = "CalorieCounter";
}
<h2>Calorie Counter</h2>
<br />
<hr />
#using (Html.BeginForm())
{
<div class="table-responsive">
<table class="table table-lg">
<tr>
<!-- Displays label and input box for CalorieIntake -->
<td>#Html.LabelFor(m => m.CalorieIntake)</td>
<td>#Html.EditorFor(m => m.CalorieIntake)</td>
</tr>
<tr>
<!-- Displays label and display for TotalCalorieCount -->
<td>#Html.LabelFor(m => m.TotalCalorieCount)</td>
<td>#Html.DisplayFor(m => m.TotalCalorieCount)</td>
</tr>
<tr>
<td></td>
<td>
<!-- Submit button triggers calculation -->
#Html.HiddenFor(m => m.TotalCalorieCount)
<input type="submit" value="Calculate New Total Calories" class="btn btn-lg btn-success"/>
</td>
</tr>
</table>
</div>
}
One last thing. If you don't want to make CalorieCount.TotalCalorieCount a nullable int, you could return a model to your view in the GET, instead, like this:
// Loads Calorie Count Page
// Sets up empty form
[HttpGet]
public ActionResult CalorieCounter()
{
return View(new CalorieCount() { TotalCalorieCount = 0 });
}
Which also fixes that part of the problem.
Ended up fixing this issue by creating a DbSet for the CalorieCount model and had this store every calculation made. The controller would loop through this database until it found the largest id showing it was the newest calculation and it will store the TotalCalorieCount in a local variable and add the CalorieIntake and send the local variable to the model so it can be displayed by the webpage.

Bind jQuery datatable values to controller parameter

I have a controller which returns a view model that has a List<string> property, and displays the results in series of text boxes in a jQuery datatable. I want to allow the user to edit the list, and post the updated data back to the controller. This is working correctly if I stay on the first page of the data table, but if I navigate to the next page and then edit one of the fields, the List<string> property on the view model is an empty list in the controller action.
Here's my view model
public class ViewModel
{
public List<string> Values { get; set; }
public ViewModel()
{
this.Values = new List<string>();
}
}
My controller actions
public ActionResult Edit()
{
ViewModel viewModel = new ViewModel();
viewModel.Values.Add("ST0001");
viewModel.Values.Add("ST0002");
viewModel.Values.Add("ST0003");
viewModel.Values.Add("ST0004");
viewModel.Values.Add("ST0005");
viewModel.Values.Add("ST0006");
viewModel.Values.Add("ST0007");
viewModel.Values.Add("ST0008");
viewModel.Values.Add("ST0009");
viewModel.Values.Add("ST0010");
return View(viewModel);
}
[HttpPost]
public ActionResult Edit(ViewModel viewModel)
{
// I have a breakpoint here to examine the values of viewModel.Values
// As long as I stay on the first page of the data table, viewModel.Values contains the updated values I type
// If I go to the second page of the table, viewModels.Values is an empty list
return RedirectToAction("Edit", viewModel);
}
Here's the datatable in the view
<table id="myTable" class="table">
<thead>
<tr>
<th>
#Html.Label("Value")
</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
for (int i = 0; i < Model.Values.Count; i++)
{
<tr>
<td>
#Html.TextBoxFor(model => Model.Values[i])
</td>
</tr>
}
}
</tbody>
</table>
#section Scripts
{
<script type="text/javascript">
$(function () {
$('#myTable').dataTable({
'order': [[0, 'asc']],
'pageLength': 5
});
});
</script>
}
The <input>'s id looks correct on each page of the datatable.
Here is what an input control on the first page looks like
Here is what an input control on the second page looks like
I'm assuming the problem is that ASP won't load a List parameter to a controller if the submitted data starts from a non-zero index? Is there any way of getting around this, such as looking at all submitted form data from my controller and manually loading each array element into the appropriate position in my list?

KendoUI cascading drop-downs does not update after binding once

I am using KendoUI cascading Drop-downs and it seems to be working fine for most part but it seems to have a little problem. However, I think it is a problem with my implementation NOT with the tool because on their Demo page here it seems to work fine. Also, I tried to follow the code exactly as it as to make sure that I do get the same behavior. Now, I am seeing following behavior:
I select an option in parent drop down and then click on the child drop down then it calls the conroller action correctly
It continues to do that as far as results for child dropdown are empty
Once it gets some value to bind child drop-down with, it stops making any call to the controller despite of what I choose in parent drop-down or child-dropdown.
I am not sure why it happens. Following is my code snippet:
Controller code
[HttpGet]
public ActionResult FindAlignmentsByTeamId(int teamId)
{
var teams = Client.GetAlignmentsByTeamId(teamId);
return Json(teams, JsonRequestBehavior.AllowGet);
}
.cshtml code
#* Perent Dropbox *#
<tr>
<td>EmployeeID</td>
<td><b>#Model.EmployeeId</b></td>
</tr>
<tr>
<td>Team</td>
<td>
#(Html.Kendo().DropDownList()
.Name("Team")
.DataTextField("TeamName")
.DataValueField("TeamId")
.DataSource(source => source.Read(read => read.Action("GetAllTeams", "Employee")))
)
</td>
</tr>
#* Child DropBox *#
#(Html.Kendo().DropDownList()
.Name("Alignment")
.DataTextField("AlignmentName")
.DataValueField("AlignmentId")
.DataSource(source => source.Read(read => read.Action("FindAlignmentsByTeamId", "Employee").Data("FilterAlignment"))
.ServerFiltering(true)
)
.CascadeFrom("teamId")
.AutoBind(false)
)
<script type="text/javascript">
function FilterAlignment() {
return {
teamId: $("#Team").val()
}
};
</script>
I am not sure what happens after it is bound successfully with a value for the first time so that it has a reason to believe that now it does not have to be checking on any OnChange() events anymore? Any ideas?
The id of your parent DropDownList is "Team", not "teamId". You need to update your child DropDownList to cascade from the correct id:
#(Html.Kendo().DropDownList()
.Name("Alignment")
.DataTextField("AlignmentName")
.DataValueField("AlignmentId"
.DataSource(source => source.Read(read => read.Action("FindAlignmentsByTeamId", "Employee").Data("FilterAlignment"))
.ServerFiltering(true)
)
.CascadeFrom("Team")
.AutoBind(false)
)

MVC4 Partial View Error "Object reference not set to an instance of an object."

First of I am a complete beginner at MVC. How would I be able to display data from the database in the events table in a partial view if a certain boolean field is true.
This is my partial view:
#model IEnumerable<TheBigEvent.Models.RecommendedEvents>
<table>
<tr>
<td>
#Html.DisplayNameFor(model => model.Event_Name)
</td>
<td>
#Html.DisplayNameFor(model => model.Event_Date)
</td>
</tr>
<tr>
#foreach (var item in Model) {
<td>
#Html.DisplayFor(modelItem => item.Event_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Event_Date)
</td>
}
</tr>
</table>
This is my controller
public ActionResult _RecommendedEvents()
{
var recommendedevents = from Events in db.Database1
select Events;
recommendedevents = recommendedevents.Where(s => s.Recommended.Equals(true));
return PartialView("_RecommendEvents", recommendedevents);
}
And the Code for displaying the partialview
#Html.Partial("_RecommmndedEvents")
This is the error I am receiving
[EDIT]
public ActionResult _RecommendedEvents(RecommendedEvents model)
{
model = new RecommendedEvents();
var recommendedevents = from Events in db.Database1
select Events;
recommendedevents = recommendedevents.Where(s => s.Recommended.Equals(true));
return View(model);
}
#{
Html.RenderAction("view","controller")
}
This will go to the given controller and action that has to return a partialview with the correct model
object reference not set to an instance of an object has always been an un initialized list for me. try initializing recommendedevents before setting it. something like
List<Events> recommendedevents = new List<Events>();
replacing Events with whatever the type is.
the first parameter in Html.Partial is the partial name not the method call. you need to either pass the model to your view thought a view model and pass it to the partial
#Html.Partial("_RecommendedEvents", Model.Events)
or load the partial through an ajax call. see my answer here for an example How do I render a partial form element using AJAX
The #HTML.Partial() function does not go through any controller action to render, it just renders the View's HTML in that spot in the document. And you aren't passing in the IEnumerable<TheBigEvent.Models.RecommendedEvents> to that partial view, so when that partial renders, the Model is null.
Put the IEnumerable<TheBigEvent.Models.RecommendedEvents> object into your main page's View Model, or maybe on something in the ViewBag, and pass it to the partial view at the time you call the Partial method:
#HTML.Partial("_RecommmndedEvents", ViewBag.RecommendedEvents)
In the top-level page's controller action, set that ViewBag.RecommendedEvents just like how you are instantiating it in your controller code above.
The error means your model is null,
PartialView() is used when you are using Ajax, otherwise you can write your code as below :
return View("_RecommendEvents", recommendedevents);

Categories