2011-04-13 50 views
2

所以我问a question last year有一个“添加项目”按钮,它会在JavaScript中的一个表单中生成一个新行,我可以返回到MVC POST动作处理程序。“添加项目”绑定到集合的表单的JavaScript按钮 - MVC3中的情况会更好吗?

举例来说,如果我有产生这样一种形式:

@for(int i = Model.Notes.Count - 1; i >= 0; i--) 
{ 
    <tr> 
     <td>@Html.HiddenFor(m => m.Notes[i].Id, new Dictionary<string, object> { { "data-index", i } }) 
     @Html.TextBoxFor(m => m.Notes[i].Timestamp, new { @class = "datepicker" })</td> 
     <td>@Html.DropDownListFor(m => m.Notes[i].PersonId, new SelectList(Model.People, "Id", "Name"))</td> 
     <td>@Html.EditorFor(m => m.Notes[i].Amount)</td> 
     <td>@Html.EditorFor(m => m.Notes[i].Comment)</td> 
    </tr> 
} 

它生成一个单行的HTML:

<tr> 
       <td><input data-index="2" data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Notes_2__Id" name="Notes[2].Id" type="hidden" value="16192"> 
       <input class="datepicker hasDatepicker valid" data-val="true" data-val-required="The Timestamp field is required." id="Notes_2__Timestamp" name="Notes[2].Timestamp" type="text" value="11/04/2011 2:11:21 PM"></td> 
       <td><select id="Notes_2__PersonId" name="Notes[2].PersonId"> 
<option value="8367">Rei</option> 
<option value="8668">Ray</option> 
<option value="8883">Roy</option> 
<option value="8814">Rob</option> 
<option value="8886">Ron</option> 
</select></td> 
       <td><input class="text-box single-line" data-val="true" data-val-number="The field Amount must be a number." data-val-required="The Amount field is required." id="Notes_2__Amount" name="Notes[2].Amount" type="text" value="0.00"></td> 
       <td><input class="text-box single-line" id="Notes_2__Comment" name="Notes[2].Comment" type="text" value="Some comment"></td> 
      </tr> 

如果我想在MVC2添加一个项目,我必须编写一些非常干燥的JavaScript代码来确定最新项目的索引,生成所有tr s,td s和input HTML,并设置要匹配的属性。

这不仅是非常重要的,如果我改变cshtml中的某些东西,我必须非常小心地确保所有的JavaScript匹配。这是一个非常糟糕的代码重复。

在MVC3中有更好的方法吗?

由于提前,

+0

你有没有得到这与MVC3的工作? – 2012-09-22 17:28:54

+0

@CiaranBruen对不起,我愿意回答,但2010-2011对我来说有点模糊,因为我幸免于一场房屋火灾,我的记忆一直很差。 – 2012-09-26 19:23:05

+0

不用担心,听起来很粗糙希望你没事:) – 2012-09-28 08:01:57

回答

1

这里有一个blog post说明,这种情况可能会更好,即使在MVC 2 :-)而且情况还可以进一步通过使用模板编辑器(也存在于MVC 2),从来不写在一个单一的for循环改善视图。

+0

哦,不错,谢谢! – 2011-04-13 20:05:44

+0

我的印象是作为MVC 2的解决方案而设计的 – Henry 2011-04-14 08:33:30

+0

那么,每次添加项目时都需要花费一笔交易,所以对于最终用户来说这不像对待我们的JS-only解决方案那样好过去,但它足够我的目的,因为我知道我的用户将在我的10ms内。 – 2011-04-14 21:34:19

0

我已经从字面上刚刚完成在做类似的事情。我需要能够添加和删除行并让它们重新编制索引。我不完全确定你的问题是什么,但我认为它与此有关。

我的功能支持你不应该有问题的东西。我的字段最初是以aaa。[n] .bbb格式生成的,当它需要是aaa [n] .bbb时,但我确定您可以更改它以符合您的需求。

在我的情况下,我添加了对AllEntries结束的局部视图,并且局部视图有一个名为Entry的div。我希望这是有道理的。我使用默认索引0,然后当部分视图已通过ajax加载时,我只是调用reindex函数,以便不需要跟踪当前索引,因此也使它可重用。

我的部分观点是这样产生的:

@model List<Address> 
@{ViewData.TemplateInfo.HtmlFieldPrefix = "Addresses";} 

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

...etc 

假设你有这样的:

<div id="AllEntries"> 

    <div id="Entry"> 
    //Form inputs... 
    </div> 

    <div id="Entry"> 
    //Form inputs... 
    </div> 

</div> 

ReindexElements($('#Entry', $('AllEntries').children()); 

//Used to reindex input elements within a given set of divs 
     //Supports changing from HtmlFieldPrefix and manual indexing 
     //E.G Set = $('#Entry' $('AllEntries').children()); 
     function ReindexElements(Set) { 
      $(Set).each(function (i, e) { 
       $('input', this).each(function (ii, element) { 
        //Current element name 
        var FieldName = (element.name); 

        //aaaa.[n].bbbb 
        //This format is created when using ViewData.TemplateInfo.HtmlFieldPrefix = "aaaa" 
        //Incorrect for reading back into a model so it must be converted to the correct format described below 
        var IncorrectFormatRegex = '((?:[a-z][a-z]+))(\\.)(\\[.*?\\])(\\.)((?:[a-z][a-z]+))'; 

        //aaaa[n].bbbb 
        //Correct format for being read back into an MVC model using TryUpdateModel() 
        var CorrectFormatRegex = '((?:[a-z][a-z]+))(\\[.*?\\])(\\.)((?:[a-z][a-z]+))'; 

        var NewFieldName; 

        var RegexSplit = new RegExp(CorrectFormatRegex, ["i"]); 
        var RegexArray = RegexSplit.exec(FieldName); 
        if (RegexArray != null) { 
         //Field name is in correct format 
         NewFieldName = RegexArray[1] + "[" + i + "]." + RegexArray[4]; 

        } else { 

         var RegexSplit = new RegExp(IncorrectFormatRegex, ["i"]); 
         var RegexArray = RegexSplit.exec(FieldName); 
         if (RegexArray != null) { 
          //Field name is incorrect format, lets fix that 
          NewFieldName = RegexArray[1] + "[" + i + "]." + RegexArray[5]; 
         } else { 
          //Hasnt matched either regex ... Name must be incorrect, exit loop 
          return false; 
         } 
        } 

        if (FieldName != NewFieldName) { 
         //Rename element 
         $(element).attr('name', NewFieldName); 
        } else { 
         //Attributes dont need renaming, exit loop 
         return false; 
        } 
       }); 
      }); 
     } 

这可能有绝对无关,与你做什么,但我希望它有帮助。

+0

好吧,那就是它的一部分......另一部分是在HTML中创建新行时实际上喷出HTML。这是一个非常单调乏味,重复性强,潜在易发生错误的部分。 – 2011-04-13 11:09:04

+0

啊我明白你的意思了。唯一的解决办法是让每一行都使用一个局部视图,将模型发布到其中,并从中填充它,而不是只需要在一个位置更新它。使用jQuery appentTo()函数,您可以加载部分视图并将其添加到

标记的末尾。因此,用一个html.partial()替换你的循环添加手动html,然后使用appendto创建一个jQuery函数在底部添加额外的函数? :) – Henry2011-04-13 11:17:07

相关问题