Reputation: 259
I am trying to wrap my head around how to pass ul li elements on Post to an MVC 4 controller. So far I understand that the ul li elements will not show up in the FormsCollection and am pretty sure that I need to pass them as a json object. So here is what I have so far based on what I could find researching ...
View Code:
<ul class="listdragable" id="OperationCountries">
<lh>@Trans["OperationCountries"]</lh>
@foreach (var item in Countries)
{
if(item.Assigned == true)
{
<li class="country" id="@item.ID" value="@item.ID" > <input type="checkbox" name="selectedCountries" id="@item.ID" >@item.Name</li>
}
}
</ul>
<p>
<button onclick="postSortOrder()">Click me</button>
@*<input type="submit" value="@Trans["Save"]" /> *@
</p>
<script type="text/javascript">
function postSortOrder() {
$.ajax({
data: { selectedCountries: $('#OperationCountries li').get() },
type: 'POST',
traditional: true
//success: updateMessage
});
}
Controller:
[HttpPost]
public ActionResult EditCountries(int id, FormCollection formCollection, List<int> selectedCountries)
when I check the value of selectedCountries the count is 0
I have also noticed that the FormCollection now only contains the selectedCountries object and non of my other form elements which I have not listed in the view code for simplicity. Also when I take the json approach I dont have access to the model as I do with the scaffolding.
So my question is how can I pass the UL LI items and the model of the view to the controller?
Thanks in advance for your thoughts
so this is what I ended up doing thanks to suggestions by Lance Hudson(Update 3 approach is what I ended up using)
I ended up taking the hidden field route
<input type="hidden" id="selectedCountryList" name="selectedCountryList" value="" />
<p>
<button class="submit" onclick="submitMyForm()">Submit</button>
</p>
<script type="text/javascript">
function submitMyForm() {
var liIds = $('#OperationCountries li').map(function (i, n) {
return $(n).attr('id');
}).get().join(',');
$('#selectedCountryList').val(liIds);
$('#myform').submit();
}
</script>
and my controller looks like
[HttpPost]
public ActionResult EditCountries(Operation operation,FormCollection formCollection)
{
string s = formCollection["selectedCountryList"].ToString();
string [] selectedCountries = s.Split(',');
}
not sure if this is the best approach or not but it works for now. I started to dabble in how to Post complex JSON Objects and overwriting the DefaultModelBinder approaches but dont have enough understanding to take that route. I still think there should be a cleaner way of passing non input, select and textarea element values combined with the model to the action methods on the controller. Especially if your trying to do anything with JQuery UI it seems ul li elements are used extensively. Any way thanks again Lance :)
Upvotes: 0
Views: 5435
Reputation: 151
Using ajax you are posting only the li's. I see two options, post the entire form using ajax or setup a handler so that on submit it copies the li data to a hidden.
Update: if you want to post the whole for using ajax you can do something like
function postSortOrder() {
$.ajax({
data: {
selectedCountries: $('#OperationCountries li').get(),
id: $('#id')
},
type: 'POST'
});
}
Update 2: mvc can handle arrays of items also. Model:
public class EditCountriesViewModel
{
public string Note { get; set; }
public int id { get; set; }
public Country[] Countries { get; set; }
}
public class Country
{
public string Name { get; set; }
public int Id { get; set; }
public bool Selected { get; set; }
}
Controller:
[HttpPost]
public ActionResult EditCountries(EditCountriesViewModel countries)
View:
@using (Html.BeginForm()) {
@Html.LabelFor(model => model.id);
@Html.EditorFor(model => model.id);
@Html.LabelFor(model => model.Note);
@Html.EditorFor(model => model.Note);
<ul>
@for(var i = 0; i < Model.Countries.Count(); i++)
{
<li class="country">@Model.Countries[i].Name @Html.CheckBoxFor(model => model.Countries[i].Selected)</li>
@Html.HiddenFor(model => model.Countries[i].Id)
}
</ul>
<input type="submit" />
}
Update 3:
function onSubmitHandler() {
$("#hidden_selectedCountriesString").val($('#OperationCountries li').get());
}
then you would need to split the result to get the numbers back into an array.
Update 4: Controller:
[HttpPost]
public ActionResult EditCountries(int id, string name, int[] enabledCountries)
View:
@using (Html.BeginForm()) {
@Html.Label("id");
@Html.TextBox("id");
@Html.Label("name");
@Html.TextBox("name");
<ul>
@foreach (var country in countries)
{
<li class="country">@country.Value <input type="checkbox" name="enabledCountries", value = "@country.Key" /></li>
}
</ul>
<input type="submit" />
}
Upvotes: 1