Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC handling Collection Item Index in Partial view model

I Have a ViewModel with a collection inside such as:

public class CreateCampaignViewModel : ControlPanelViewModel
{
    [RequiredField]
    public string Name { get; set; }

    public List<AdvertisementViewModel> Advertisements { get; set; }
    ...
}

in the View, if i use it like:

@for (int i = 0; i < Model.Advertisements.Count; i++)
{
  <fieldset style="z-index: 0;">
  <legend>מודעה</legend>
  <table style="width: 100%;">
    <tr>
      <td>
        <label for="@Html.NameFor(m => m.Advertisements[i].Title)">כותרת הפרסומת</label></td>
      <td>@Html.TextBoxFor(m => m.Advertisements[i].Title)</td>
    </tr>
  </table>
  </fieldset>
}

everything is good, and i can see the list when i post the form...

but i want to nest the AdvertisementEditor in a Partial View hence my view becomes:

@for (int i = 0; i < Model.Advertisements.Count; i++)
{
   Html.RenderPartial("AdvertisementEditor", Model.Advertisements[i]);
}

and my Partial:

@model Pushed.Models.AdvertisementViewModel

<fieldset style="z-index: 0;">
    <legend>מודעה</legend>
    <table style="width: 100%;">
        <tr>
            <td>
                <label for="@Html.NameFor(m => m.Title)">כותרת הפרסומת</label></td>
                <td>@Html.TextBoxFor(m => m.Title)</td>
        </tr>
    </table>
</fieldset>

My problem is that Now, when i post the form, i dont get the values in the TextBox for each Advertisement.

This is logical, cause now my <input> tags dont have the 'advertisement[1].Title' name, but only 'Title' which does not exist in my containing model.

how can i create a partial that is reflecting a single collection item with it's indecies so it will repost correctly with the form?

like image 689
Tomer W Avatar asked Dec 26 '22 14:12

Tomer W


2 Answers

found a solution, Can't believe i didn't find this before!

there are two ways to tell MVC.NET to prefix input fields:

  1. create EditorTemplate instead of PartialView... and it will work just great.

  2. define TemplateInfo.HtmlFieldPrefix

calling the Partial View as illustrated:

@{ 
  Html.RenderPartial("TargetAudienceParameters", Model.TargetAudienceParameter, 
      new ViewDataDictionary {
           TemplateInfo = new TemplateInfo {
               HtmlFieldPrefix = "Advertisements[4]" // 4 being an example
           } 
      }); 
 }
like image 59
Tomer W Avatar answered Dec 28 '22 06:12

Tomer W


In my project when I trigger with this problem I'm starting to use ajax query, which hit after user away from textbox. It's not clearest solution but works for me. Also you need to generate special Id in partial view for each group element. Smth about:

function eduFacilityTableSave() {
    $('#eduFacilityTable tr input[type="text"],#eduFacilityTable tr select').change(function () {
        var parId = $(this).parent().parent().attr('id');
        var parentName = parId.replace(/\d+/g, '');
        var parentId = parId.replace(/\D+/g, '');
        var id = $(this).attr('id');
        var text = $(this).val();
        //alert(text);
        $.ajax({
            type: "POST",
            //contentType: "application/json; charset=utf-8",
            url: "/Form/SaveFromForm/",
            data: { id: id, parentId: parentId, parentName: parentName, text: text },
            dataType: "json",
            success: function (data) {
                //
            }
        });
    });
}

public JsonResult SaveFromForm(string id, string parentId, string parentName, string text) {
            if (parentName == "eduFacility") {
                var edufacility = _repository.GetEduFacilityById(Convert.ToInt32(parentId));
                if (id == "EntryYearId") {
                    edufacility.EntryYearId = Convert.ToInt32(text);
                }
                if (id == "FinishYearId") {
                    edufacility.FinishYearId = Convert.ToInt32(text);
                }
                if (id == "FullName") {
                    edufacility.FullName = text;
                }
                if (id == "Speciality") {
                    edufacility.Speciality = text;
                }
                if (ModelState.IsValid) {
                    _repository.UpdateEduFacility(edufacility);
                    _repository.Save();
                }
            }
            return Json("Success", JsonRequestBehavior.AllowGet);
        }
like image 26
BorHunter Avatar answered Dec 28 '22 06:12

BorHunter