MVC equilvelant of repeater with multiple form elements and checkbox to select - model-view-controller

I need to replicate the functionality you get with an asp repeater that contains checkboxes, textboxes, and the occasional dropdownlist in an MVC application. Om traditional webforms you get a postback event and its pretty easy to get at all the controls and their values associated with the checkbox (id).
Anybody have any good suggestions on how to get the values back on a post for the items that have the checkbox checked. I am able to get some arrays back in the FormCollection (and even a strongly typed view) but I have not been able to figure out a good way to link the values effectivly.
All rows have a checkbox and a textbox, some rows also have a dropdownlist
To further explain...
row 1 has a checkbox and a textbox
row 2 has a checkbox a textbox, and a dropdown list.
if the user selects row 1 and 2, I need to get the values for all the form elements (for some calculations). Also, I haven't come up with a good method of handling validation errors.
any suggestions are greatly appreciated.

The simplest thing to do would be to iterate the collection for which you would have a repeater for. Using Razor syntax:
#using (Html.BeginForm()) {
<table>
#for (var i = 0; i < Models.Items.Count; i++) {
<tr>
<td>
#Html.CheckBoxFor(x => Model.Items[i].SomeBool)
</td>
<td>
#Html.TextBoxFor(x => Model.Items[i].SomeString)
</td>
</tr>
}
</table>
<button type="submit">Go</button>
}
Then a controller method:
[HttpPost]
public ActionResult Index(MyViewModel viewModel) {
// view model will be bound to values in form
}
Assuming the the Model in the view is of type MyViewModel. Once you have a sense of how this works you can look into ASP.NET MVC grid frameworks.

Related

DropDownListFor loses list binding in validation

I am using fluentvalidation and mvc3. I have a drop down list, and it works well. I wanted to test my validation and it works EXCEPT that on validation the drop down list is empty??
What I mean is that if I purposely submit while the default SelectListItem Please Select...with a value of zero is chosen then the submit fails validation and the message shows etc. but my dropdownlist is now empty??
My controller code populating the list:
if (extforum.Count > 0)
{
foreach (var s in extforum)
model.ExternalSubscription.AvailableForums.Add(new SelectListItem(){ Text = s.ForumName, Value = s.Id.ToString() });
}
else
model.ExternalSubscription.AvailableForums.Add(new SelectListItem() { Text = "None Available", Value = "0" });
//add default value
model.ExternalSubscription.AvailableForums.Add(new SelectListItem() { Text="Please Select", Value="0", Selected=true });
My razor code:
<tr>
<td>
#Html.LabelFor(model => model.ForumName):
</td>
<td>
#Html.DropDownListFor(model => model.SelectedExtBoardId, Model.AvailableForums)
#Html.RequiredHint()
#Html.ValidationMessageFor(model => model.ExtForumBoardId)
</td>
</tr>
My validator code:
RuleFor(x => x.ExtForumBoardId)
.NotEqual(0).WithMessage("Blah"));
In your HttpPost controller action you must populate the AvailableForums collection property on your view model the same way you did in your Get action that rendered the form. This is necessary if you intend to redisplay the same view containing the dropdown. This often happens in the case of a validation error. Don't forget that when you submit a form, only the selected value of the dropdown is sent to the server. The collection of all possible values is something that you need to retrieve from your backend if you intend to redisplay the same view.

How can i restric listbox to single select in asp.net MVC3,razor

Iam using ASP.Net MVC3 Razor, I have two listboxes in .cshtml, let's say lbox1 and lbox2. I have binded data in the controller and sent to listboxes using viewbag. Both the listboxes have same data in it like A,B,C,D.But we can select more than one items from the listbox.. Now i want lbox1 selectionmode as single.
How can i restric it to single select ???
I have a controller where i binded the data
public Actionresult Index()
{
ViewBag.lbox1= new SelectList(db.boxes, "ID", "Name");
}
This is my view
<table>
<tr>
<td>
#Html.ListBox("lbox1")
</td>
<td>
#Html.ListBox("lbox2")
</td>
</tr>
</table>
could any one help me
Use a DropDown instead of a ListBox:
#Html.DropDown("lbox1")

Dynamically Add Rows when using Editor Templates and EditorFor in MVC 3

Expanding on a previous question, I'm using EditorFor to edit a list of objects of type (let's say) Hobby.
Now, I need to implement functionality to add editors for individual Hobby objects, so that the user can add additional hobbies.
I read Steven Anderson's blog about how to do that in MVC 2. However, he's rendering the individual Hobby instances using a loop and RenderPartial, rather than using EditorFor. I understand his approach of making Ajax calls to render another partial view and inserting the view result into the DOM, but don't know how to apply the Ajax add in my case, with EditorFor.
His code:
<% foreach (var item in Model)
Html.RenderPartial("GiftEditorRow", item);
%>
My code is using EditorFor like this:
// Model is a List<Hobby>
#Html.EditorFor(model => model.AllowedSurveys)
How do I add an additional Hobby editor, given that the editor is implemented as an Editor Template rather than as a Partial View?
You could replace your editor template with a partial:
#foreach (var item in Model.AllowedSurveys)
{
Html.RenderPartial("_Hobby", item);
}
and inside the partial (~/Views/controllerName/_Hobby.cshtml):
#model Hobby
<div class="editorRow">
#using(Html.BeginCollectionItem("AllowedSurveys"))
{
#Html.EditorFor(x => x.Name)
...
}
</div>
The Html.BeginCollectionItem custom helper is used to generate names with Guids and allow for reordering and adding new items to the collection using javascript. You can download it from the updated article. The one you were reading was for ASP.NET MVC 1 and is obsolete.

Stripes Checkboxes and Textfields

All -
I'm using stripes to do some form input for a problem I'm working on and I'm stuck on how best to submit a a pair of data using stripes and checkboxes.. for example my page looks like the following:
I have a list of options where users can enable a selection by clicking the box, and also supply some input for that item by entering data into the text field next to it:
<tr>
<td><stripes:checkbox name="item.enable" value="${item.id}"/></td>
<td><stripes:text name="item.value" value="${item.value}"/></td>
</tr>
.....
next item...
When the form is submitted I'd expect my Collection<Item> to be populated yet that's not the case..
How can I best submit a pair of items using the check box fields.
Thanks in advance.
..Chris
Read the documentation on indexed properties. You need to tell Stripes that you have multiple items, by naming them items[0], items[1], etc.:
<tr>
<td><stripes:checkbox name="items[0].enable" value="${item.id}"/></td>
<td><stripes:text name="items[0].value" value="${item.value}"/></td>
</tr>
<tr>
<td><stripes:checkbox name="items[1].enable" value="${item.id}"/></td>
<td><stripes:text name="items[1].value" value="${item.value}"/></td>
</tr>
This supposes that you action bean has a setItems(List<Item> items) method, that the Item class has a public no-arg constructor, and has a setEnable(String itemId) and a setValue(String value) method.
I would wrap this in a JSTL 'forEach' tag and I would put the items in a List. Similar to what JB Nizet said, you also need public setters in the action bean. If you are using Collection<Item> with some implementation other than List<Item> the below snippet won't work.
<c:forEach var='itemIndex' begin='0' end='2'>
<c:set scope='page' var='item' value='${items[itemIndex]}'>
<tr>
<td><stripes:checkbox name="items[${itemIndex}].enable" value="${item.id}"/></td>
<td><stripes:text name="items[${itemIndex}].value" value="${item.value}"/></td>
</tr>
</c:forEach>
There is another case when you don't want the list to default to 3 items. The one I'm thinking of is when the list is already populated. If that is the case I would change the 'end' attribute of the <c:forEach> to be: ${fn:length(actionBean.items) == 0 ? 3 : fn:length(actionBean.items)-1}

MVC3 Listbox Contents to Model Values

I'm using ASP.NET MVC3 and I was wondering if there's any way to create a listbox that contains the values which I would like my model to have.
Using #Html.ListBoxFor will only store the selected items into the model when the form is submitted rather than all the items in the listbox. I plan on using javascript to add items from another textbox.
Thanks
You are not clear, but are you trying to POST values back? If so, then they must be selected (i.e. active) form values in order to POST. If you use JavaScript to add options to a listbox (HTML select> then these don't post. You would need a multi-select enabled select and then flag each value you want to submit as selected.
To get values back they need to POST in some manner.
No. This has nothing to do with MVC3. This is a limitation of the HTTP model. When a form is posted, the browser only posts the selected value. It does not post the other elements of the select list.
MVC must work within the framework of the way the browsers work, and this can't be changed.
Yes, you can do this. You need a couple things to make this work though, it can be troubling.
In view:
//generate list box with
<select id="NAMEOFLISTBOX" name="NAMEOFLISTBOX" multiple="multiple">
Okay, here is the part that most people miss. The controller will only collect selected items if they are actually designated to be selected. Therefore, where your submit button is you need to include some javascript.
<input type="submit" value="DO WORK" onclick="selectLISTBOXITEMS()" />
Script:
function selectLISTBOXITEMS(){
var curList = document.getElementById("NAMEOFLISTBOX");
for (var i = 0; i < curList.length; i++) {
curList.options[i].selected = true;
}
}
In controller:
[HttpPost]
public ActionResult controllerName(List<string> NAMEOFLISTBOX)
{
foreach(string s in NAMEOFLISTBOX)
{
//do work
}
return RedirectToAction("controllerGet");
}
Not impossible, but the first time I did this it took a while to figure out why nothing was being sent.

Resources