使用部分与淘汰赛模板整合剃刀形式编辑集合(Razor form with editable coll

2019-10-18 02:09发布

因此,标题是有点做作,但是这基本上是我想要完成的任务:

<ul data-bind="template: { name: 'ItemFormTemplate', foreach: Items }">
    @foreach (var item in Model.Items)
    {
        Html.RenderPartial("_ItemForm", item);
    }
</ul>

<script type="text/html" id="ItemFormTemplate">
    @{ Html.RenderPartial("_ItemForm", new Item()); }
</script>

这里的想法是:

  1. 我想对表单Item是局部的,我想用相同部分的剃刀的的foreach和喂养淘汰赛模板两者。 (我不想重复HTML也可以建立只为淘汰赛特殊版本。)

  2. 剃刀的foreach是后备的情况下,JavaScript被禁用或不支持。 形式应仍是可编辑和submittable(作为模型中的粘合剂将处理正确的POST数据),有或没有JavaScript。

  3. 当然,这意味着该字段名称都需要遵循类似的模式Items[0].SomeField 。 部分将被强类型仅一个Item ,虽然(而不是IEnumerable<Item> 可以理解的是,这将不是真的有可能为淘汰赛模板,因为目前指数将只提供客户端。 我有我已经使用了一个解决办法:

     ko.bindingHandlers.prefixAndIndex = { init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { if (bindingContext.$index) { var prefix = ko.utils.unwrapObservable(valueAccessor()); var $element = $(element); $element.find('input,textarea,select').each(function () { var $this = $(this); var newId = prefix + '_' + bindingContext.$index() + '__' + $this.attr('id'); var newName = prefix + '[' + bindingContext.$index() + '].' + $this.attr('name'); $('label[for=' + $this.attr('id') + ']').attr('for', newId); $this.attr('id', newId); $this.attr('name', newName); }); } } }; 

    这只是结合模板(的顶级元素<li>在这种情况下)和搜索和替换所有标识和名称以适当的前缀属性。 这似乎工作得很好,但任何批评或改进建议,欢迎。

说真的,我现在挣扎的唯一的事情是获得适当的前缀到部分当剃刀的foreach内。 通常,你会使用这一个解决for ,而不是foreach ,然后通过索引项而不是只是一个普通的项目,即:

@for (var i = 0; i < Model.Items.Count(); i++)
{
    @Html.TextBoxFor(m => m.Items[i].SomeField)
}

但是,这并不使用部分时,因为一旦你进入部分,你仍然只是一个单一的处理工作Item ,断章取义。

所以,最迫切的问题是我怎么能仍然使用局部强类型Item ,但仍然有它知道任何指数目前的? 然后,除此之外,如何最好地减少重复或HTML和逻辑(增加代码重用)。 我在正确的轨道上我的思维上休息。 请问有什么可以改善或做的更好?

编辑

我应该指出, 最好我想保留,部分强类型和实际利用。 换句话说,我希望能够做@Html.TextBoxFor(m => m.SomeField)而不是伪造它像@Html.TextBox("Items[" + iterator + "].SomeField") 如果我必须走这条路,这是一两件事,但我希望有一个更好的办法。

我想我也可以做线沿线的东西:

@Html.TextBox(prefix + "[" + iterator + "]." + Html.NameFor(m => m.SomeField))

然后通过prefixiterator到部分。 那是在我没有处理硬编码值感更好,但它是一个很多额外的逻辑尤其是持续了部分与一群领域。 同样,希望有个更好的办法。

Answer 1:

你的问题指出,关于如何在前缀asp.net的MVC被处理的扩散知识的缺乏,因为在10天内没有能够nothwitstanding有几种方式来传递的前缀,在一个干净的方式,以你的部分提出一个“accettable”解决方案视图:

1,您可以得到同样的效果

@Html.TextBoxFor(m => m.Items[i].SomeField)

通过使用DisplayFor或EditorFor调用局部视图:

@Html.DisplayFor(m => m.Items[i].SomeField)

您既可以定义一个显示/编辑模板,项目数据类型相同的名称,或者干脆通过局部视图到EditorFor / DisplayFor助手的名字。 欲了解更多信息,请点击这里 。

2,您还可以使用以前的答案的的RenderPartial相同超负荷传给你想它分配给物业使用到的ViewDataDictionary完整的前缀:ViewDataDictionary.TemplateInfo.HtmlFieldPrefix

一旦你做到了这一点,你所提供的前缀将被自动添加到所有输入字段名。

所以,如果你写的:

@Html.TextBoxFor(m => m.Property)

文本框将有名称:Prefix.Property,其中前缀是你传递的前缀

ViewDataDictionary.TemplateInfo.HtmlFieldPrefi



Answer 2:

所以,最迫切的问题是我怎么能仍然使用局部强类型的项目,但仍然有它知道任何指数目前的?

我想,你只是想知道数组中的索引,你应该传递中的ViewDataDictionary。

@for (var i = 0; i < Model.Items.Count(); i++){
  Html.RenderPartial("_ItemForm", Model.Items[i], new ViewDataDictionary(){
    { "index", i }
  });
}


文章来源: Razor form with editable collection using partial with Knockout template integration