仅更新mvc 3页面中包含的部分视图?

时间:2012-12-26 03:02:08

标签: ajax asp.net-mvc sql-update partial-views

我有一个 MVC 3 页面,它返回一个用户响应列表,其中包含每个响应的名为“memo”(显示/添加备忘录)的部分视图。当我向响应添加备忘录时,它应该更新数据库和该响应的备忘录列表。它应该是通过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调用(示例代码)以及控制器的外观如何?当ajax调用成功时,如何更新列表备忘录div="memos"以反映新备忘录?

  3. 来自Response的表单操作是否会与部分视图Memo的表单操作冲突?

2 个答案:

答案 0 :(得分:2)

问题答案:

  1. 你不应该将responseId传递给partial,你应该从你的响应对象中传递memo集合,并使你的局部视图强烈地键入到该集合中。
  2. 请参阅下面的完整代码示例。
  3. 您不需要部分中的表单,因为您正在进行简单的ajax调用以添加新备忘录。请参阅下面的完整代码示例。
  4. 这是我目前正在处理的项目的修改示例:

    需要遵循一些代码,所以这里有:

    这是我的模特。职业规划表上有几个部分,其中一个部分是选择和更新能力的部分。 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 partial:/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>
    }
    

    查看/ 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);
    

    我希望这会有所帮助。如果您有任何其他问题,请与我们联系。

答案 1 :(得分:1)

虽然您可以通过返回包含更新内容的部分视图来解决问题,但您也可以考虑使用jQuery的加载方法。

查看here,特别是在&#34;加载页面片段&#34;部分。基本上你可以再次获得原始页面,jQuery将提取&#34;提取&#34;您想要的内容,只要它可以被选择器(例如div id)定位。

注意,此解决方案并不适用于所有情况,因为服务器的响应中会有冗余标记,因为您将丢弃其余页面内容并仅使用更新的部分。