質問への回答:
- responseId をパーシャルに渡すべきではありません。応答オブジェクトからメモ コレクションを渡し、パーシャル ビューをそのコレクションに強く型付けする必要があります。
- 以下の完全なコード例を参照してください。
- 新しいメモを追加するために単純な ajax 呼び出しを行っているため、パーシャルにフォームは必要ありません。以下の完全なコード例を参照してください。
これは、私が現在取り組んでいるプロジェクトの変更例です。
従うべきコードが少しあるので、ここに行きます:
これが私のモデルです。キャリア プランニング フォームにはいくつかのセクションがあり、そのうちの 1 つがコンピテンシーを選択して更新するセクションです。SelectCompetencies モデルには、コンピテンシーのコレクションが含まれています。ユーザーはコンピテンシーを追加できます。完了すると、データベースに追加され、部分的なコンピテンシーのリストが更新されます。
public class CareerPlanningFormViewModel
{
// code removed ...
public SelectCompetenciesModel SelectCompetencies { get; set; }
// code removed ...
}
public class SelectCompetenciesModel
{
public int CareerPlanningFormID { get; set; }
public IList<CompetencyModel> Competencies { get; set; }
public byte MaximumCompetenciesAllowed { get; set; }
}
public class CompetencyModel
{
public int CompetencyID { get; set; }
public int? CompetencyOptionID { get; set; }
public string ActionPlan { get; set; }
public IDictionary<int, string> CompetencyOptions { get; set; }
}
キャリア プランニング フォームのメイン ビュー: /Views/CPF/CareerPlanningForm.cshtml
@model MyNamespace.Models.CareerPlanningForm.CareerPlanningFormViewModel
<link rel="stylesheet" href="@Url.Content("~/Content/CreateCPF.css")" />
@using (Html.BeginForm())
{
// other sections loaded here...
// code removed for brevity...
@Html.Partial("SelectCompetencies", Model.SelectCompetencies)
// other sections loaded here...
// code removed for brevity...
}
SelectCompetencies パーシャル: /Views/CPF/SelectCompetencies.cshtml ユーザーは新しいアクション プランのテキストを入力し、[コンピテンシーの追加] ボタンをクリックします。それは ajax 経由で CPFController/NewCompetencyTemplate に投稿されます
@model MyNamespace.Models.CareerPlanningForm.SelectCompetenciesModel
@Html.HiddenFor(m => m.CareerPlanningFormID)
<h3>Select Competencies</h3>
<p class="guidance">
Select up to @Model.MaximumCompetenciesAllowed competencies to focus on improving.
</p>
<table id="CompetenciesTable">
<thead>
<tr>
<th>Competency</th>
<th>Action Plan:</th>
</tr>
</thead>
<tbody>
@for (int i = 0; i < Model.Competencies.Count(); i++)
{
@Html.EditorFor(m => m.Competencies[i])
}
</tbody>
<tfoot id="CompetenciesTableFooter" class="@(Model.Competencies.Count() < Model.MaximumCompetenciesAllowed ? "" : "hidden")">
<tr>
<td colspan="2">
@Html.TextArea("NewActionPlanText")
@Html.Button(ButtonType.Button, "Add Another Competency", "add", new { id = "AddCompetencyButton" })
</td>
</tr>
</tfoot>
</table>
@section script
{
<script>
jQuery(document).ready(function ($) {
var competenciesTableBody = $('#CompetenciesTable tbody'),
competenciesTableFooter = $('#CompetenciesTableFooter'),
addCompetencyButton = $('#AddCompetencyButton'),
newCompetencyTemplateUrl = '@Url.Content("~/CPF/NewCompetencyTemplate")',
count = competenciesTableBody.find('tr').length,
newActionPlanText = $('#NewActionPlanText'),
careerPlanningFormID = $('#CareerPlanningFormID');
addCompetencyButton.click(function () {
$.ajax({
url: newCompetencyTemplateUrl(),
type: 'POST',
data: {
careerPlanningFormID: careerPlanningFormID,
actionPlan: newActionPlanText,
itemCount: count
},
dataType: 'html',
success: function (data) {
var elements = $(data);
// other code removed here...
competenciesTableBody.append(elements);
// other code removed here...
}
});
});
});
</script>
}
Views/CPF/EditorTemplates/CompetencyModel.cshtml
@model MyNamespace.Models.CareerPlanningForm.CompetencyModel
<tr class="competency">
<td>
@Html.DropDownListFor(m => m.CompetencyOptionID, new SelectList(Model.CompetencyOptions, "Key", "Value"), "Select competency...")
</td>
<td>
@Html.TextAreaFor(m => m.ActionPlan, new { @class = "competencyActionPlan" })
@Html.HiddenFor(m => m.CompetencyID)
</td>
</tr>
新しいコンピテンシーを追加するアクションを含むコントローラー: /Controllers/CPFController.cs
これにより、CareerPlanningFormService が呼び出されて新しいコンピテンシーが追加され、新しいコンピテンシーをレンダリングする NewCompetencyTemplate の部分ビューが返されます。
public class CPFController : Controller
{
private readonly ICareerPlanningFormService careerPlanningFormService;
public CPFController(ICareerPlanningFormService careerPlanningFormService)
{
this.careerPlanningFormService = careerPlanningFormService;
}
[HttpPost]
public PartialViewResult NewCompetencyTemplate(int careerPlanningFormID, int itemCount, string newActionPlanText)
{
var count = itemCount + 1;
// Even though we're only rendering a single item template, we use a list
// to trick MVC into generating fields with correctly indexed name attributes
// i.e. Competencies[1].ActionPlan
var model = new SelectCompetenciesModel
{
Competencies = Enumerable.Repeat<CompetencyModel>(null, count).ToList()
};
model.Competencies[count - 1] = this.careerPlanningFormService.BuildNewCompetencyModel(careerPlanningFormID, newActionPlanText);
return this.PartialView(model);
}
}
私のサービス クラス: CareerPlanningFormService.cs
これはビジネス ロジックを処理し、リポジトリを呼び出してアイテムをデータベースに追加し、新しい CompetencyModel を返します。
public class CareerPlanningFormService : ICareerPlanningFormService
{
private readonly IMyRenamedRepository repository;
private readonly IPrincipal currentUser;
public CareerPlanningFormService(
IMyRenamedRepository repository,
IPrincipal currentUser)
{
this.repository = repository;
this.currentUser = currentUser;
}
public CompetencyModel BuildNewCompetencyModel(int careerPlanningFormID, string newActionPlanText)
{
var competency = new Competency
{
CareerPlanningFormID = careerPlanningFormID,
CompetencyOptionID = null,
ActionPlan = newActionPlanText
};
this.repository.Add(competency);
this.repository.Commit();
return new CompetencyModel
{
CompetencyID = competency.CompetencyID,
CompetencyOptionID = competency.CompetencyOptionID,
ActionPlan = competency.ActionPlan,
CompetencyOptions = this.GetCompetencyOptionsForCareerPlanningFormID(careerPlanningFormID)
};
}
}
ここで、NewCompetencyTemplate のパーシャル: Views/CPF/NewCompetencyTemplate.cshtml
これは非常に単純です。コレクション内の最後のコンピテンシー (追加したばかり) に対して、上記と同じエディター テンプレートをレンダリングするだけです。
@model MyNamespace.Models.CareerPlanningForm.SelectCompetenciesViewModel
@Html.EditorFor(m => m.Competencies[Model.Competencies.Count() - 1])
ajax 呼び出しが成功すると、呼び出したコントローラー アクション メソッドからこの部分が返されます。次に、パーシャルを取得して、コンピテンシー テーブル本体に追加します。
// snippet from ajax call above
competenciesTableBody.append(elements);
これが役立つことを願っています。他にご不明な点がありましたらお知らせください。