Reputation: 35
I have a partial view inside a form that append to the form each time a button is clicked. It is a text area with a set of responses. How can I pass my model from the view to the controller, add it to the list model and back to view?
I am passing ReviewFormViewModel I want to pass the ListAdhoc to the partial controller and add items to it then pass it back to the view.
public class ReviewFormViewModel
{
...// other fields
public List<AdhocViewModel> ListAdhoc { get; set; }
}
public class AdhocViewModel
{
public int? ReviewId { get; set; }
public String AdhocQuestion { get; set; } //free form
public int? SelectedAnswer { get; set; } // for binding int? for optional
public String Comments { get; set; }
public List<AdhocOptionsVM> ListAdhocOptions { get; set; }
}
public class AdhocOptionsVM
{
public int AnswerId { get; set; }
public String RatingName { get; set; }
public Decimal Rating { get; set; }
public String ActiveFl { get; set; }
}
controller for partial view
public PartialViewResult Adhoc()
{
//pass model object on button click and add each item to the model everytime
var AdhocObj = new AdhocViewModel();
AdhocObj.ListAdhocOptions = new List<AdhocOptionsVM>();
var query = db.dbQuestionOptions.Where(qo => qo.ActiveFl == "Y").OrderByDescending(qo => qo.Rating).ToList();
foreach (var item in query)
{
var AdhocAnsOptionsVMObj = new AdhocOptionsVM();
AdhocAnsOptionsVMObj.AnswerId = item.AnswerId;
AdhocAnsOptionsVMObj.RatingName = item.RatingName;
AdhocAnsOptionsVMObj.Rating = item.Rating;
AdhocAnsOptionsVMObj.ActiveFl = item.ActiveFl;
AdhocObj.ListAdhocOptions.Add(AdhocAnsOptionsVMObj);
}
return PartialView("Adhoc", AdhocObj);
}
and partial view that is using the ReviewFormViewModel aswell:
<div class="adhoc">
@using (Html.BeginCollectionItem("adhoc"))
{
<div class="panel panel-success">
<div class="panel-heading">
@Html.HiddenFor(m => m.ReviewId)
@Html.HiddenFor(m => m.AdhocId)
@Html.TextAreaFor(m => m.AdhocQuestion, htmlAttributes: new { @style = "width:650px", @placeholder = "Enter Adhoc Question here" })<br />
</div>
<div class="panel-body">
@foreach (var optAnswer in Model.ListAdhocOptions)
{
<div class="radio">
<responselabel>@Html.RadioButtonFor(m => m.SelectedAnswer, optAnswer.AnswerId, new { id = optAnswer.AnswerId }) @optAnswer.RatingName</responselabel><br />
</div>
}
<div>@Html.ValidationMessageFor(m => m.SelectedAnswer)</div><br />
@Html.TextAreaFor(m => m.Comments, htmlAttributes: new { @style = "width:650px", @placeholder = "Comments" })<br /><br />
</div>
<button type="button" class="delete">Delete</button>
</div>
}
main view
@model CustomerFeedback.Areas.ProjectManagers.Models.ReviewFormViewModel
@{
ViewBag.Title = "CreateFormsIndex";
}
<h4 align="center">Project Review Form</h4>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div class="text-center">
<h4>
@Html.DisplayName(Model.ProjectId) @Html.DisplayName(Model.ProjectName)
</h4>
<h4>
PM: @Html.DisplayName(Model.FullName)
</h4>
</div>
</div>
</div>
</div>
<div class="container">
<br />
<div class="panel-group">
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(m => m.ProjectId)
@Html.HiddenFor(m => m.AccountId)
@Html.HiddenFor(m => m.ReviewDate)
<div class="panel panel-default">
<div class="panel-body">
<div class="panel-group">
<div class="panel-heading">
<h4 class="panel-title">
Required Questions
</h4>
</div>
@for (int i = 0; i < Model.ListReqQuestions.Count; i++)
{
<div class="panel panel-success">
<div class="panel-heading">
@Html.HiddenFor(m => m.ListReqQuestions[i].QuestionId)
@Html.DisplayFor(m => m.ListReqQuestions[i].QuestionText)
</div>
<div class="panel-body">
@foreach (var optAnswer in Model.ListReqQuestions[i].ListQuestionOptions)
{
<div class="radio">
<responselabel>@Html.RadioButtonFor(m => m.ListReqQuestions[i].SelectedAnswer, optAnswer.AnswerId, new { id = optAnswer.AnswerId }) @optAnswer.RatingName</responselabel><br />
</div>
}
<div>@Html.ValidationMessageFor(m => m.ListReqQuestions[i].SelectedAnswer)</div><br />
@Html.TextAreaFor(m => m.ListReqQuestions[i].Comments, htmlAttributes: new { @style = "width:650px", @placeholder = "Comments" })<br /><br />
</div>
</div>
}
<div class="panel-heading">
<h4 class="panel-title">
Optional Questions
</h4>
</div>
@for (int i = 0; i < Model.ListOpQuestions.Count; i++)
{
<div class="panel panel-success">
<div class="panel-heading">
@Html.HiddenFor(m => m.ListOpQuestions[i].QuestionId)
@Html.DisplayFor(m => m.ListOpQuestions[i].QuestionText)
</div>
<div class="panel-body">
@foreach (var optAnswer in Model.ListOpQuestions[i].ListQuestionOptions)
{
<div class="radio">
<responselabel>@Html.RadioButtonFor(m => m.ListOpQuestions[i].SelectedAnswer, optAnswer.AnswerId, new { id = optAnswer.AnswerId }) @optAnswer.RatingName</responselabel><br />
</div>
}
<div>@Html.ValidationMessageFor(m => m.ListOpQuestions[i].SelectedAnswer)</div><br />
@Html.TextAreaFor(m => m.ListOpQuestions[i].Comments, htmlAttributes: new { @style = "width:650px", @placeholder = "Comments" })<br /><br />
</div>
</div>
}
@*on click (new adhoc question) add a new freeform question with list of answers*@
<div class="panel panel-success" id="adhoc">
@* renders partial adhoc view *@
</div>
<br />
<div class="center">
<input type="button" value="New Adhoc Question" class="btnAdhoc btn-success" />
</div>
<br />
<div class="center">
<input type="submit" value="Save" name="Command" class="btn btn-success" />
<input type="submit" value="Submit" name="Command" class="btn btn-success" />
<input type="submit" value="Cancel" name="Command" class="btn btn-success" />
<input type="submit" value="Attach" name="Command" class="btn btn-success" />
</div>
</div>
</div>
</div>
}
</div>
</div>
<script>
$(function () {
$('.btnAdhoc').click(function (event) {
event.preventDefault();
$.ajax({
url: '/ProjectManagers/Forms/Adhoc',
//data: JSON.stringify(model),
type: 'get',
success: function (result) {
$('#adhoc').append(result);
}
});
});
})
</script>
UPDATE: I've added the AdhocViewModel.
Ive added the view model for those properties. I have a form with a set of questions and responses to be answered. Those are from the database. I have a button, on click will generate the partial view and append to the form (can be many). The partial view consists of a text area (for any question entered), set of responses (from database) and a comment box. I am not sure how to handle this on post (submit). My attempt is to pass the model from the view to the partial controller, add items to it and pass it back to the view for processing. I am not have any success on passing model data
UPDATE 2 Updated code with using BeginCollectionItem helper. Added main view
Upvotes: 1
Views: 1192
Reputation:
The reason that the collection does not bind is because the parameter in BeginCollectionItem()
must match the name of you property. Change it to
@using (Html.BeginCollectionItem("ListAdhoc")) // binds to List<AdhocViewModel> ListAdhoc
In addition you also need a loop in the main view to render existing AdhocViewModel
in the collection. Even if none exist initially, it is still required in case you need to return the view because ModelState
is invalid. In the main view include
<div class="panel panel-success" id="adhoc">
@foreach(var item in Model.ListAdhoc)
{
@Html.Partial("Adhoc", item)
}
</div>
Upvotes: 1