I have a form that has a section where it uses jQuery tab generated by BeginCollectionItem. This is done by one-to-many relationship. I can create multiple tabs within the form and can submit it (newForm.cshtml). However, when it comes to editing, especially when I have to retrieve the form (with multiple tabs filled with information), I am kinda stuck here.
So the scenario is simple. I have a table that shows the list of submitted forms and can click an edit link of a row to edit that retrieved form. At this moment, I can only retrieve the Name in NewForm, but other Names associated with Family tabs are not retrieved.
Model:
public class NewForm
{
public int NewFormId { get; set; }
public string Name { get; set; }
public ICollection<Family> Families{ get; set; }
}
public class Family
{
public int FamilyId { get; set; }
public string Name { get; set; }
public int NewFormId { get; set; }
public virtual NewForm NewForm{ get; set; }
}
Edit.cshtml:
@model Test.Models.NewForm
@using (Html.BeginForm("Edit", "NewForm", FormMethod.Post))
{
<p>Your Name</p>
@Html.EditorFor(m => m.Name)
<button type="button" id="addFamily" name="addFamily">Add Family</button>
<div id="tabs">
<ul>
<li><a href="#tabs-family">Family 1</a></li>
</ul>
<div id="tabs-family">
@Html.Action("AddNewFamily", "NewForm")
</div>
</div>
<button type="submit">Save</button>
}
<script>
$(function () {
var tabTemplate = "<li><a href='#{href}'>#{label}</a></li>",
familyTabCounter = 2,
var tabs = $("#tabs").tabs();
$('#addFamily').on('click', function (event) {
$.ajax({
url: '/NewForm/AddNewFamily',
}).success(function (partialView) {
addTab(partialView, this.url);
});
event.preventDefault();
});
// Actual addTab function: adds new tab using the input from the form above
function addTab(partialView, url) {
if (url == "/NewForm/AddNewFamily") {
var label = "Family " + familyTabCounter,
id = "tabs-family" + familyTabCounter,
li = $(tabTemplate.replace(/#\{href\}/g, "#" + id).replace(/#\{label\}/g, label));
tabs.find(".ui-tabs-nav").append(li);
tabs.append("<div id='" + id + "'><p>" + partialView + "</p></div>");
tabs.tabs("refresh");
familyTabCounter++;
}
}
});
</script>
Family.cshtml:
@model Test.Models.Family
<div class="editorRow">
@using (Html.BeginCollectionItem("families"))
{
@Html.EditorFor(m => m.Name)
}
</div>
Controller:
public PartialViewResult AddNewFamily()
{
return PartialView("~/Views/NewForm/PartialView/Family.cshtml");
}
public ActionResult Edit(int? id)
{
NewForm form = db.NewForms
.Include(i => i.Families)
.Where(x => x.NewFormId == id)
.Single();
return View(form);
}
How can I retrieve information for families(tabs) associated with newForm?
Edit
@using (Html.BeginForm("Edit", "NewForm", FormMethod.Post))
{
<p>Your Name</p>
@Html.EditorFor(m => m.Name)
<button type="button" id="addFamily" name="addFamily">Add Family</button>
@{int number = 1;}
@foreach (var family in Model.Families)
{
<div id="tabs">
<ul>
<li><a href="#tabs-family">Family @number</a></li>
</ul>
<div id="tabs-family">
@Html.Partial("../NewForm/Family", family)
</div>
</div>
number++;
}
<button type="submit">Save</button>
}
I've reflected Stephen's advice and retrieving multiple families is working, but now I face another problem that I can't create each tab for each family. I tried with my code, but it creates tab, but it is placed in a weird place. Any suggestions?
You need to generate a tabs for each
Familyin your collection using 2 loops, one to create the headers (the<li><a>elements), and one for the content (the<div>elements.Note that your current implementation is generating duplicate
idattributes, and you need to ensure that each content<div>has a uniqueidattribute, and that the associated header<a>element has matchinghrefvalue.Side note: In your current script, you need to set the
familyTabCounterusingso that clicking the 'Add' button will generate the correct
idattribute and associated fragment identifier based on the number of existingFamilyin the collection.