Get values with Multiple checkboxes in Razor MVC4 - c#

Currently I'm working on MVC4 web application, I need to get values which are selected or not from multiple checkboxes from the web page. Here is my code in View to render checkboxes.
using (Html.BeginForm("Controller", "NameSpace", FormMethod.Post))
{
#foreach (var Leave in Model)
{
<tr class="Row">
<td>
#Html.CheckBox("leaves")
</td>
<td>#Leave.EmployeeId</td>
<td>#Leave.EmployeeName</td>
</tr>
}
<input type="submit" name="btn" value="Approve"/>
<input type="submit" name="btn" value="Reject"/>
}
How can I get those checkBox's values in my controller...?

put a name on the check box(es)and you can pull the value on the controller using request
#Html.CheckBox("leaves", new { name = "leaves" })
then on then controller
string selected = Request.Form["leaves"].ToString();
string[] selectedList = selected.split(',');
foreach(var temp in selectedList){
// do something with the result
}
this will return a comma delimited list (1,5,8) of the id's of all of the selected checkboxes (if there are more than 1).

You better use:
string[] selectedList =Request.Form.GetValues("leaves");
Instead of:
string selected = Request.Form["leaves"].ToString();
string[] selectedList = selected.split(',');
for getting an array instead of one concatenated string which needed to be splitted.
Moreover, in this way you don't have to worry about having commas in your values.

Related

Binding the checked attribute of html input to boolean method return value in blazor

I am working on a blazor project currenty. In this project I need to add some default values to a list in my C# code. The problem is that I can not find a way to bind a boolean method return value to the "checked" attribute of an input.
Code:
I do have a list and I am adding an input (checkbox) field per entry in this list to my html:
#foreach (ProfessionViewModel prof in Professions)
{
<div class="form-group m-1">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="#prof.Id"
#onchange="eventArgs => { ToggleProfessions(prof, eventArgs.Value); }" />
</div>
</div>
}
I cant find a way to bind the "checked" attribute to a method that checks if this item exists in an other list (SelectedProfessions list, defined in #code section).
My list:
public List<ProfessionViewModel> SelectedProfessions { get; set; } = new List<ProfessionViewModel>();
My boolean return method:
private bool CheckIfProfessionIsAssigned(ProfessionViewModel prof)
{
if (SelectedProfessions.Contains(prof))
return true;
return false;
}
Problem description:
The collection "Professions" contains all professions available in the app. In this form the user should be able to select certain professions individualy (for a profession filter).
Every selected profession is contained in the collection "SelectedProfessions". The problem is that I can't bind (or render) the checkboxes value according to the helper property "CheckIfProfessionIsAssigned", which determines if this profession is currently selected by the user.
Didn't try these myself, but based on this answer - https://stackoverflow.com/a/60343185 - something like this might work to initially check the checkboxes:
<input type="checkbox" checked="#CheckIfProfessionIsAssigned(prof)">
You could alternatively try to create a dictionary of integers and booleans named professionsSelected in which to store for each profession ID if it is selected or not, and then bind that to the checkboxes, like:
<input type="checkbox" #bind="#professionsSelected[prof.Id]" />

Form within a foreach loop not posting the model back to the controller

I've searched around and can't find an answer to my problem.
I've got a View that takes accepts Foo in like so:
#model IEnumerable<MyApplication.Models.Foo>
Inside of the view I've got a table. I populate the the table just doing a simple foreach loop through my Foo model. I have added a column where a user can add details to each row in a text area and save.
So the view looks like this:
#foreach (var item in Model)
{
<tr>
<th>
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(u => item.Id)
#Html.TextAreaFor(u => item.Details, new { #class = "form-control" })
<input type="submit" value="Save" class="btn btn-sm btn-default" />
}
</th>
</tr>
}
My controller is setup like this:
[HttpPost]
public ActionResult AddDetails(Foo foo)
{
}
When I set a breakpoint on that controller foo always has null values for the Details property and the Id is always 0. When it's passed into the view it's got all of the properties set to right, so I'm not sure why it is not posting back properly?
I've tried this:
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post, new { foo = Model }))
I have also tried removing the foreach loop and changing it to pass in just a single Model to the View and for the View to accept just the single model instead of an IEnumerable. When I do this it posts back just fine.
And that does not work either. I'm wondering if it has something to do with the fact that my form is within a foreach loop and perhaps I need to do a little more work like add a data-id attribute to the element and just capture the click event on the button and do an AJAX call to the controller and pass the right values along that way?
EDIT Sorry I completely forgot the view model. Here is what that looks like:
public class Foo
{
public int Id { get; set; }
public string Details { get; set; }
}
Generally speaking it's bad form to post to a different model than what your form view is composed from. It makes a lot of things difficult, not the least of which is recovering from validation errors.
What you're doing here is looping through a list of Foo and creating multiple forms that will each submit only a single Foo to an action that takes only a single Foo. While the post itself is fine, using the *For helpers on a model that is not the same as what you're posting to will likely not generate the proper input names necessary for the modelbinder to bind the posted values onto that other model. At the very least, if you need to return to this view because of a validation error, you will not be able to keep the user's posted data, forcing them to repeat their efforts entirely.
Ideally, you should either post the entire list of Foo and have just one form that wraps the iteration (in which case, you would need to use for rather than foreach). Or you should simply list the Foos with a link to edit a particular Foo, where you would have a form for just one Foo.
try to do this.possible problems
form should outside the table
single form for whole table
wrap your column editor inside tbody not thead
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post))
{
//thead and tbody
}
Since no answer was reported for testing the for loop instead of foreach.
I was stuck all day yesterday using foreach loop and always got 0 items in the post method. I changed to for loop and was able to receive the updated items in the post method.
For reference I am using asp.net core 3.2
This is the foreach loop:
#{
foreach(var role in #Model.RolesList)
{
<div class="btn-check m-1">
<input type="hidden" asp-for="#role.RoleId" />
<input type="hidden" asp-for="#role.RoleName" />
<input asp-for="#role.IsSelected" class="form-check-input" />
<label class="form-check-label" asp-for="#role.IsSelected">#role.RoleName</label>
</div>
}
}
This is the for loop:
#for(int i = 0;i< Model.`enter code here`RolesList.Count();i++)
{
<div class="btn-check m-1">
<input type="hidden" asp-for="RolesList[i].RoleId" />
<input type="hidden" asp-for="RolesList[i].RoleName" />
<input asp-for="RolesList[i].IsSelected" class="form-check-input" />
<label class="form-check-label" asp-for="RolesList[i].IsSelected">#Model.RolesList[i].RoleName</label>
</div>
}

Unable to submit List of model in MVC [duplicate]

This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 7 years ago.
I am displaying a list of items in a Collection in edit mode in a view. after editing the documents, I want to submit. But I am unable to postback the list. List shows null.
here is my View
#model List<NewsLetter.Models.NewsLetterQuestions>
#using (Html.BeginForm("GetAnswersfromUser", "NewsLetter", FormMethod.Post, null))
{
#Html.AntiForgeryToken()
foreach (var item in Model) {
<div>
#Html.DisplayFor(modelItem => item.Question)
</div>
<div>
#Html.TextAreaFor(modelItem => item.Answer)
</div>
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Submit" class="btn btn-default" />
</div>
</div>
}
Here is my Controller
public ActionResult GetAnswersfromUser(string id)
{
id = "56c5afc9afb23c2df08dd2bf";
List<NewsLetterQuestions> questions = new List<NewsLetterQuestions>();
var ques = context.NewsLetterQuestionCollection.Find(Query.EQ("NewsLetterId", id));
foreach(var x in ques)
{
questions.Add(x);
}
return PartialView(questions);
}
[HttpPost]
public ActionResult GetAnswersfromUser(List<NewsLetterQuestions> nql)
{
string id = "56c5afc9afb23c2df08dd2bf";
foreach (var item in nql)
{
var query = Query.And(Query.EQ("NewsLetterId", id), Query.EQ("Question", item.Question));
var update=Update<NewsLetterQuestions>
.Set(r => r.Answer, item.Answer);
context.NewsLetterQuestionCollection.Update(query,update);
}
return RedirectToAction("NewsLetterIndex");
}
When i hit submit it throws error.
System.NullReferenceException: Object reference not set to an instance of an object.
In the line
foreach (var item in nql)
which means that nql is null.
In order for the model binder to be able to bind the posted data, all your input names need to be in the format of [N].Property, where N is the index of the item within the list. In order for Razor to generate the input names properly, then, you need to pass it an indexed item, which means you need a for loop, rather than a foreach:
#for (var i = 0; i < Model.Count(); i++)
{
...
#Html.TextAreaFor(m => m[i].Answer)
...
}
You're never passing the list back to the controller's Post handler. You need to route the list back to the controller.
You should be doing something similar to this untested code :)
Html.BeginForm("Index", "Home", new { #nql=Model }, FormMethod.Post)
Take a look at this post as well. It is similar to your issue: Pass multiple parameters in Html.BeginForm MVC4 controller action and this Pass multiple parameters in Html.BeginForm MVC

How to align radiobutton list values horizontally and vertically in mvc4?

I have around 35 radio button list values to be displayed in my view using #html.RadioButtonFor html helper in a .cshtml page.
I want to display in 9 columns and 4 rows.
In Asp.net using control properties of like "RepeatLayout", "RepeatDirection", "RepeatColumns" we could achieve this.
Same thing I want to apply it for mvc4.Is there any way to implement the same?
Please help!
Controller code:
ViewBag.Ratio = query.Select(m => new SelectListItem { Value = m.RatioID, Text = m.Ratio_Description });
.cshtml code
<td colspan="3" >
#foreach (var item in (IEnumerable<SelectListItem>)ViewBag.Ratio)
{
#Html.RadioButtonFor(m => m.RatioType, new { #item.Value, #item.Text })
<label for = "#item.Value">#item.Text</label>
}
</td>
Best way is to use table like this: http://jsfiddle.net/z2L3qbh9/1/
Or try to manage it with css like this:
.eachRadioBtn{
width:11%;
float:left;
}
wrap each radioBottuon with a div tag:
<div class=".eachRadioBtn">
#HTML.RadioButtonFor( ... )
</div>

How can I make sure that the newest items added to the list variable gets placed in the top and not in the bottom when it get displayed in html?

I am using MVC + EF
I have a Feed xml file url that gets updated every 7 minute with items, every time a new item gets added I retrieve all the items to a list variable and then I add these varible to my database table. After that I fill a new list variable which is my ViewModel from the database table. Then I declare the ViewModel inside my view which is a .cshtml file and loop throught all of the objects and display them.
How can I make sure that the newest items get placed on the top and not in the bottom?
This is how I display the items inside my cshtml note that I use a ++number so the newest item needs to be 1 and so on.. :
#model Project.Viewmodel.ItemViewModel
#{
int number = 0;
}
}
<div id="news-container">
#foreach (var item in Model.NewsList)
{
<div class="grid">
<div class="number">
<p class="number-data">#(++number)</p>
</div>
<p class="news-title">#(item.Title)</p>
<div class="item-content">
<div class="imgholder">
<img src="#item.Imageurl" />
<p class="news-description">#(item.Description) <br />#(item.PubDate) | Source</p>
</div>
</div>
</div>
}
</div>
This is how I fill the viewmodel which I use inside the .cshtml file to iterate throught and display the items
private void FillProductToModel(ItemViewModel model, News news)
{
var productViewModel = new NewsViewModel
{
Description = news.Description,
NewsId = news.Id,
Title = news.Title,
link = news.Link,
Imageurl = news.Image,
PubDate = news.Date,
};
model.NewsList.Add(productViewModel);
}
Sorry for the paint lol :P
Any kind of help is appreciated
#foreach (var item in Model.NewsList.OrderByDescending(n => n.PubDate)

Categories

Resources