4

各応答に対して「メモ」(メモを表示/追加する) と呼ばれる部分ビューを含むユーザー応答のリストを返す MVC 3 ページがあります応答にメモを追加すると、その応答のデータベースとメモのリストが更新されます。部分ビュー「メモ」のみに影響する ajax による部分ページ更新である必要があります。

「メモ」を含むビュー Response.chtml:

@using (Html.BeginForm("Response", "User", FormMethod.Post, new { id = "UserResponse" }))
   {
      .... code removed ....
@foreach (var response in Model)
                {
                <div class="qna"><input type="text" id=@response.responseId value="@response.ResponseText" />  

                 <div>@Html.Partial("_memo", response.responseId)</div>
                }
        .....

部分ページ「_memo.chtml」:

<div>add memo</div> 

<ul id="memos">                                          
@foreach (var memo in Model) {                           
    <li>@memo.Text</li>                                       
}                                                           
</ul>                                                       

<form method="post" id="memoForm"                        
      action="@Url.Action("AddMemo")">                   

    @Html.TextArea("Memo", new { rows = 5, cols = 50 })   
    <br />
    <input type="submit" value="Add" />
</form> 

ユーザー/応答を表示するためのコントローラー:

[HttpGet]
        public ActionResult Response(id)
        {
           .....
            return View(responses);

上記のコードから始めたばかりです。空白を埋めるのに助けが必要です。

  1. 応答 ID を部分ビューに渡す場合、その応答のメモのリストを取得するにはどうすればよいですか? それにはajaxが含まれますか?(代わりに.. Partial("_memo", response.memos))

  2. ajax 呼び出しで部分ビューを更新するにはどうすればよいですか。クライアント側の ajax 呼び出し (サンプル コード) とは何ですか? また、コントローラーはどのように見えますか? div="memos"ajax 呼び出しが成功した場合、新しいメモを反映するようにリスト メモを更新するにはどうすればよいですか?

  3. Response からのフォーム アクションは、部分ビュー メモのフォーム アクションと競合しますか?

4

2 に答える 2

2

質問への回答:

  1. responseId をパーシャルに渡すべきではありません。応答オブジェクトからメモ コレクションを渡し、パーシャル ビューをそのコレクションに強く型付けする必要があります。
  2. 以下の完全なコード例を参照してください。
  3. 新しいメモを追加するために単純な 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);

これが役立つことを願っています。他にご不明な点がありましたらお知らせください。

于 2012-12-28T13:14:16.040 に答える
1

更新されたコンテンツを含む部分的なビューを返すだけでそれを実行できることは正しいですが、jQueryのloadメソッドの使用を検討することもできます。

ここ、特に「ページフラグメントの読み込み」セクションを見てください。基本的に、元のページを再度取得するだけで、jQueryは、セレクター(div idなど)でターゲットにできる限り、必要なコンテンツを「抽出」します。

ページコンテンツの残りの部分を破棄し、更新された部分のみを使用するため、サーバーからの応答に冗長なマークアップが存在するため、このソリューションはすべての場合に適しているわけではないことに注意してください。

于 2012-12-26T18:26:09.173 に答える