2014-04-14 67 views
1

我有一個使用大量AJAX的ASP.NET MVC頁面。在最基本的層面上,它包含一系列問題,每個問題都有一個問題清單。我的觀點模型(大大簡化了這一問題的緣故):在列表中添加一個新項目由編輯器模板呈現

視圖模型:

public class QuestionViewModel 
{ 
    .... 
    public string QuestionText { get; set; } 
    public List<AnswerViewModel> AnswerList { get; set; } 
    public bool EditMode { get; set; } 
    .... 
} 

public class AnswerViewModel 
{ 
    .... 
    public string Answer { get; set; } 
    .... 
} 

_View.cshtml:

@model QuestionViewModel 

@if(Model.EditMode) 
{ 
    @Html.EditorFor(x => x) 
} 
else 
{ 
... 
} 

QuestionViewModel.cshtml(編輯模板):

@model Project.Models.QuestionViewModel 

.... 
@Html.EditorFor(x => x.AnswerList) 
.... 

AnswerViewModel.cshtml(編輯模板):

@model KSUAdvising.Models.AnswerViewModel 

.... 
@Html.TextBoxFor(x => x.Answer) 
.... 

^^^這EditorFor呼叫使我的答案列表罰款(用適當的指數沿着這樣的模型綁定將綁定回到列表恰如其分。即:

<input id="AnswerList_0__Answer" name="AnswerList[0].Answer" type="text" value="Yes"> 
<input id="AnswerList_1__Answer" name="AnswerList[1].Answer" type="text" value="No"> 

然而,在客戶端,我需要的物品,當用戶點擊一個按鈕添加到這個列表。這需要發生在客戶端,因此在用戶保存問題之前不會更改數據庫。

我看到幾個方向去解決這個問題:

  1. 做一個AJAX調用服務器來渲染回一個新的空白答案,並把它添加到DOM。然而,由於這個問題脫離了問題的上下文,它不會呈現正確的名稱(索引),並且它不會被模型聯編程序拾取。
  2. 向客戶端呈現隱藏的HTML「模板」,包括正確的輸入名稱,然後克隆該模板並修改名稱索引以滿足模型聯編程序。這看起來有點冒失,很難正確渲染這個模板。

這似乎是一種常見的情況,但我很難提出一個很好的解決方案。這種情況下推薦的方法是什麼?

回答

0

這取決於...爲了表現,我不會去第一個選項。通過Ajax加載新項目的這種輕微延遲可能令人討厭。

個人大多數時候我只是在客戶端完全構建一個HTML元素。我知道這會讓維護變得複雜,因爲無論何時您對模型集合進行更改,都必須記住更改客戶端邏輯,但這很快且直截了當。

也有一個想法如何提高你的第二個選項。基本上,你不需要有一個真正的對象來構建它。

@Html.TextBoxFor(model => model.Items[int.MaxValue], new { style= "display:none" }) 

輸入渲染

<input name="Items[2147483647]" id="Items_2147483647_" style="display: none;" type="text" value=""> 

請注意,該項目屬性是在我的情況下空,但它並不重要,如果你只是想建立一個模板xxxFor HTML輔助只是使用表達式構建HTML。此外,在用真實索引克隆模板時,很容易替換int.MaxValue。使用int.MaxValue作爲佔位符是安全的,但它非常不靈活,您將在頁面上擁有很多項目。

希望它有幫助!

1

我投票選項2

渲染一個隱藏的HTML項模板。然後在客戶端按鈕上單擊,克隆模板並修改索引。

在cshtml頁面中,在foreach之後,爲模板添加一個新的隱藏div。給它一個索引佔位符(我使用_x0x_)。創建一個新的空項目,然後像在foreach中那樣渲染它。 (你也可以擁有的項目呈現爲局部視圖,然後調用它的foreach內部和外部)。

下面是示例CSHTML頁:

@foreach (var role in roles) 
{ 
    int roleIndex = roles.IndexOf(role); 
    string rolePrefix = "CasePartyRoles[" + roleIndex + "]."; 
    <div id="[email protected]" class="row brdr-bttm mrgn-bttm-sm"> 
     <div class="col-md-10 mrgn-bttm-sm"> 
      @Html.Hidden(rolePrefix + "SequenceNo", role.SequenceNo) 
      @Html.Hidden(rolePrefix + "RowVersion", role.RowVersion) 
      @Html.DropDownListFormGroupFor(modelItem => role.PartyRoleCode, (SelectList)ViewBag.PartyRoleSelectList, null, "col-md-3", "col-md-9", null, role.PartyRoleCode, rolePrefix + "PartyRoleCode") 
      @Html.DropDownListFormGroupFor(modelItem => role.PartyStatusCode, (SelectList)ViewBag.PartyStatusSelectList, null, "col-md-3", "col-md-9", null, role.PartyStatusCode, rolePrefix + "PartyStatusCode") 
      @Html.EditorFormGroupFor(modelItem => role.SubFileNo, "col-md-3", "col-md-9", null, null, rolePrefix + "SubFileNo") 
      @Html.EditorFormGroupFor(modelItem => role.PartyRank, "col-md-3", "col-md-9", null, null, rolePrefix + "PartyRank") 
     </div> 
    </div> 
} 
<div id="CasePartyRoleTemplate" class="hidden"> 
    @*Template for new Role*@ 
    @{ 
     var newRole = new CasePartyRole(); 
     string newRolePrefix = "CasePartyRoles[_x0x_]."; 
    } 
    <div id="CasePartyRoleIndex__x0x_" class="row brdr-bttm mrgn-bttm-sm"> 
     <div class="col-md-10 mrgn-bttm-sm"> 
      @Html.Hidden(newRolePrefix + "SequenceNo", newRole.SequenceNo) 
      @Html.Hidden(newRolePrefix + "RowVersion", newRole.RowVersion) 
      @Html.DropDownListFormGroupFor(modelItem => newRole.PartyRoleCode, (SelectList)ViewBag.PartyRoleSelectList, null, "col-md-3", "col-md-9", null, newRole.PartyRoleCode, newRolePrefix + "PartyRoleCode") 
      @Html.DropDownListFormGroupFor(modelItem => newRole.PartyStatusCode, (SelectList)ViewBag.PartyStatusSelectList, null, "col-md-3", "col-md-9", null, newRole.PartyStatusCode, newRolePrefix + "PartyStatusCode") 
      @Html.EditorFormGroupFor(modelItem => newRole.SubFileNo, "col-md-3", "col-md-9", null, null, newRolePrefix + "SubFileNo") 
      @Html.EditorFormGroupFor(modelItem => newRole.PartyRank, "col-md-3", "col-md-9", null, null, newRolePrefix + "PartyRank") 
     </div> 
    </div> 
</div> 

這裏是一個小jQuery函數添加的項目基於模板:

function createItemFromTemplate(templateId, indexNo, insertBeforeId) { 
    // Copy the template Element, replaces all the _x0x_ with the index no and add the new element 
    $(insertBeforeId).before($.parseHTML($(templateId).clone().prop('outerHTML').replace(/_x0x_/g, indexNo))); 
} 
相關問題