Reputation: 1339
TL;DR: I just need to figure out why i can't serialize() the partial view's parent div and receive the model. Coding this out manually will take forever as there are many parent partials I'd have to use the same logic on.
More info: I've tried EditorTemplate for binding purposes, but unfortunately there is no easy way to use them as variable lists as far as I've searched.
Begin:
Models
public class ContactModel
{
public List<ContactDetailModel> Contacts { get; set; }
....
public class ContactDetailModel
{
public ContactView Contact { get; set; }
public PhoneModel PhoneModel { get; set; }
...
public class PhoneModel
{
public int ContactId { get; set; }
public int IsPrimaryPhoneNumberId { get; set; }
public List<PhoneView> Phones { get; set; }
public List<EmailPhoneTypeView> EmailPhoneTypes { get; set; }
...
To select & post inputs from just this partial view, I've implemented a variable class, and its relative template prefix to keep the MVC binding for the partial view.
@{
var phoneClass = "phone" + @Model.Contacts[index].Contact.ContactId;
var phoneTemplatePrefix = "Contacts[" + index + "].PhoneModel";
}
This is ran inside of a loop, increasing indexes as needed to keep binding.
<div class="@phoneClass">
@Html.Partial("_ContactPhone", Model.Contacts[index].PhoneModel, new ViewDataDictionary() { TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = phoneTemplatePrefix } })
</div>
The partial I'm attempting to post. (Strongly Typed partial for PhoneModel
)
@{var addNavigationClass = "AddContactPhone" + Model.ContactId;}
for (var phoneIndex = 0; phoneIndex < Model.Phones.Count(); phoneIndex++)
{
@Html.HiddenFor(model => model.Phones[phoneIndex].ContactPhoneId)
@Html.DropDownListFor...
@Html.TextBoxFor(model => model.Phones[phoneIndex].PhoneNumber)
<a href="#" class="removeMemberPhone">Trash</a>
@Html.RadioButtonFor(model => model.IsPrimaryPhoneNumberId, Model.Phones[phoneIndex].ContactPhoneId) Primary</label>
}
Inside the View's click function
var model = $('.phone' + '@Model.ContactId' + ' :input').serialize();
console.log('model', model);
$.ajax({
url: '/Contact/AddPhone',
type: 'POST',
data: model,
success: function (data) {
console.log(data.length);
}
....
The log's output
model Contacts%5B1%5D.PhoneModel.Phones%5B0%5D.ContactPhoneId=3907&Contacts%5B1%5D.PhoneModel.Phones%5B0%5D.EmailPhoneTypeId=1&..........
My model never has any values in my controller (I've abbreviated ContactPhoneModel to PhoneModel in the above code)...
Upvotes: 1
Views: 1101
Reputation: 1339
Here's a bit of (unrefined, and early) code that I've written, that will take properly formatted serializeArray() data and re base the arrays for a good post to the MVC controller.
Top 2 lines will show how to call it once in your project.
Upvotes: 0
Reputation: 7172
This is more pseudo code than actual code, you will need to tidy this up a bit.
Since you aren't posting back the full page, it seems overkill to jump through the Mvc model binders hoops when binding to a collection. If it was me doing this, I'd alter your click handler to the following:
var model = {};
$('.phone' + '@Model.ContactId' + ' :input').each(function(){
model[/[^\.]+$/.exec($(this).prop("name"))[0]] = $(this).val();
};
console.log('model', model);
$.ajax({
url: '/Contact/AddPhone',
type: 'POST',
data: model,
contentType: "application/json; charset=UTF-8",
success: function (data) {
console.log(data.length);
}
I would look at using editortemplates as mentioned in the comments, they will take some of the pain away of managing indexes and the like
Upvotes: 1