2013-02-05 46 views
7

我有一個視圖模型女巫包含迭代項目。我通過EditorFor()方法將它們放在我的視圖中。MVC4如何將訂單項動態添加到EditorFor字段?

查看:

@model Models.MyModel 

@using (Html.BeginForm(@Model.Action, @Model.Controller)) 
{ 
    <div class="section" id="Terms"> 
     @Html.EditorFor(m => m.Terms) 
    </div> 

    <input type="submit" value="Save" /> 
} 

型號:

public class MyModel 
{ 
    public IEnumerable<Term> Terms { get; set; } 
} 

EditorTemplates \ Term.cshtml:

@model Models.Term 

@if (Model != null) 
{ 
    <fieldset> 
     <legend>Term</legend> 

     @Html.HiddenFor(model => model.TermID) 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.Identifier) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.Identifier) 
      @Html.ValidationMessageFor(model => model.Identifier) 
     </div> 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.Description) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.Description) 
      @Html.ValidationMessageFor(model => model.Description) 
     </div> 

    </fieldset> 
} 

我要到b Ë能夠動態地從列表視圖中的添加/刪除項目,像knockout.js這個例子,但我如何保存自動ID的MVC創建??:

http://knockoutjs.com/examples/cartEditor.html

這裏有我這方面的要求:

  • 添加新條款
  • 刪除條款
  • 驗證添加
  • 新條款的意見

我讀過其他問題,因此我還沒有找到真正的明確答案。 knockout.js是接受的方式嗎?有Knockout和MVC這樣做的例子嗎?

謝謝!

回答

0

你想淘汰賽MVC http://knockoutmvc.com/CartEditor

您不必使用淘汰賽對於這一點,你真正需要的是JavaScript和驗證,並創建/刪除其映射到對事物的MVC側寧靜的控制器操作的動作。你如何去實現這個取決於你。敲除使得它很容易。

+0

我看到這是如何工作的但是,這並沒有真正顯示如何在EditorFor()中使用它。我不再需要使用它嗎?這個例子沒有在BeginForm()和post方法中顯示它,模型綁定是否正確? –

0

你需要做以下幾點:

  1. 發送模式,控制器和渲染一個可編輯的字段項。
  2. 您要求用戶提交此內容或點擊添加以添加更多條款。
  3. 如果用戶點擊添加,您將創建一個現有字段的副本並清空它們或任何它們以創建新的字段。
  4. 當用戶提交時,您將其發回到接受條款數組並將其添加到數據庫或不包含的數據的操作。或者你可以使用像上面例子中那樣的ajax,或者從this example你可以看到它發送給服務器的是json數組對象,而不是用命名元素形成的。
  5. 您可以在創建它們時處理它們,也可以在提交時處理它們。

取決於應用程序以及使淘汰賽只是幫助你在客戶端的第3步要在其中創建從舊版本新。您也可以爲此提起JQuery模板,並使用json2與舊瀏覽器支持進行序列化。

所有你需要明白的是,一旦你在客戶端,你已經發送了你的模型一次,所以不要擔心服務器端。無論你在客戶端構建的是什麼,都可以一次發送一個模型來保存以term id和其他信息重新生成json的Terr動作,或者可以將saveTerm的集合作爲json數組返回並且它可以正常工作。

如果您正在考慮在postBack上發送數組而不是ajax,只保留表單元素名稱相同並重復輸入字段併發送。 MVC會將它們映射到一系列術語,就像它與json一樣。

1

我發現這個職位Nested Collection Models in MVC3由Jarrett Meyer,誰有一個解決方案,不使用挖空和最大限度地重複使用代碼。

這包括添加和刪除方法。我將在這裏概述add方法。

示範

public class Person { 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public IList<PhoneNumber> PhoneNumbers { get; set; } 
    public IList<EmailAddress> EmailAddresses { get; set; } 
    public IList<Address> Addresses { get; set; } 
} 

查看

//New.cshtml:  
@using (Html.BeginForm("New", "Person", FormMethod.Post)) 
{ 
    @Html.EditorForModel() 
    <p> 
    <button type="submit"> 
     Create Person 
    </button> 
    </p> 
} 

//Person.cshtml: 
@Html.AntiForgeryToken() 
@Html.HiddenFor(x => x.Id) 

<p> 
    <label>First Name</label> 
    @Html.TextBoxFor(x => x.FirstName) 
</p> 
<p> 
    <label>Last Name</label> 
    @Html.TextBoxFor(x => x.LastName) 
</p> 
<div id="phoneNumbers"> 
    @Html.EditorFor(x => x.PhoneNumbers) 
</div> 
<p> 
    @Html.LinkToAddNestedForm("Add Phone Number", "#phoneNumbers", ".phoneNumber", "PhoneNumbers", typeof(PhoneNumber)) 
</p> 

//PhoneNumber.cshtml: 
<div class="phoneNumber"> 
    <p> 
    <label>Telephone Number</label> 
    @Html.TextBoxFor(x => x.Number) 
    </p> 
    <br/> 
</div> 

助手

/// <param name="linkText">Text for Link</param> 
/// <param name="containerElement">where this block will be inserted in the HTML using a jQuery append method</param> 
/// <param name="counterElement">name of the class inserting, used for counting the number of items on the form</param> 
/// <param name="collectionProperty">the prefix that needs to be added to the generated HTML elements</param> 
/// <param name="nestedType">The type of the class you're inserting</param> 
public static IHtmlString LinkToAddNestedForm<TModel>(this HtmlHelper<TModel> htmlHelper, string linkText, 
    string containerElement, string counterElement, string collectionProperty, Type nestedType) 
{ 
    var ticks = DateTime.UtcNow.Ticks; 
    var nestedObject = Activator.CreateInstance(nestedType); 
    var partial = htmlHelper.EditorFor(x => nestedObject).ToHtmlString().JsEncode(); 

    partial = partial.Replace("id=\\\"nestedObject", "id=\\\"" + collectionProperty + "_" + ticks + "_"); 
    partial = partial.Replace("name=\\\"nestedObject", "name=\\\"" + collectionProperty + "[" + ticks + "]"); 

    var js = string.Format("javascript:addNestedForm('{0}','{1}','{2}','{3}');return false;", containerElement, 
     counterElement, ticks, partial); 

    TagBuilder tb = new TagBuilder("a"); 
    tb.Attributes.Add("href", "#"); 
    tb.Attributes.Add("onclick", js); 
    tb.InnerHtml = linkText; 

    var tag = tb.ToString(TagRenderMode.Normal); 
    return MvcHtmlString.Create(tag); 
} 

private static string JsEncode(this string s) 
{ 
    if (string.IsNullOrEmpty(s)) return ""; 
    int i; 
    int len = s.Length; 

    StringBuilder sb = new StringBuilder(len + 4); 
    string t; 

    for (i = 0; i < len; i += 1) 
    { 
     char c = s[i]; 
     switch (c) 
     { 
      case '>': 
      case '"': 
      case '\\': 
       sb.Append('\\'); 
       sb.Append(c); 
       break; 
      case '\b': 
       sb.Append("\\b"); 
       break; 
      case '\t': 
       sb.Append("\\t"); 
       break; 
      case '\n': 
       //sb.Append("\\n"); 
       break; 
      case '\f': 
       sb.Append("\\f"); 
       break; 
      case '\r': 
       //sb.Append("\\r"); 
       break; 
      default: 
       if (c < ' ') 
       { 
        //t = "000" + Integer.toHexString(c); 
        string tmp = new string(c, 1); 
        t = "000" + int.Parse(tmp, System.Globalization.NumberStyles.HexNumber); 
        sb.Append("\\u" + t.Substring(t.Length - 4)); 
       } 
       else 
       { 
        sb.Append(c); 
       } 
       break; 
     } 
    } 
    return sb.ToString(); 
} 

的Javascript

//since the html helper can change the text of the item inserted but not the index, 
//this replaces the 'ticks' with the correct naming for the collection of properties 
function addNestedForm(container, counter, ticks, content) { 
    var nextIndex = $(counter).length; 
    var pattern = new RegExp(ticks, "gi"); 

    content = content.replace(pattern, nextIndex); 
    $(container).append(content); 
} 
+0

添加嵌套表單高度依賴於具有可能不會在慢速計算機上發生的'ticks'屬性的唯一值。爲了確保這一點,你可以使用一個GUID或者做一些事情:System.Threading.Thread.Sleep(1);長蜱= DateTime.UtcNow.Ticks; –

相關問題