Asp.net mvc 在Knockout中绑定多个partialView

Asp.net mvc 在Knockout中绑定多个partialView,asp.net-mvc,knockout.js,asp.net-mvc-5,Asp.net Mvc,Knockout.js,Asp.net Mvc 5,我有一个jQuery手风琴,每个面板都包含一个表单。所有表单都相同,输入共享相同的ID、名称和数据绑定属性 假设每个表单都有不同的绑定上下文(使用ko with:),如果有两个表单 然而,我事先不知道会有多少种形式。我正在为MVC ViewModel的表单集合中的每个表单对象呈现PartialView(其中包含表单) @model ViewModel <div class="container-fluid"> <div id="jQueryAccordion">

我有一个jQuery手风琴,每个面板都包含一个表单。所有表单都相同,输入共享相同的ID、名称和数据绑定属性

假设每个表单都有不同的绑定上下文(使用
ko with:
),如果有两个表单

然而,我事先不知道会有多少种形式。我正在为MVC ViewModel的表单集合中的每个表单对象呈现PartialView(其中包含表单)

@model ViewModel

<div class="container-fluid">
    <div id="jQueryAccordion">

        @foreach (var form in Model.AllForms.ToList())
        {
           <!-- ko with: items[@form.Key] -->
           Html.RenderPartial("_Form", form);
           <!-- /ko --> 
        }

        // etc.
@model视图模型
@foreach(Model.AllForms.ToList()中的变量形式)
{
Html.RenderPartial(“_Form”,Form);
}
//等等。

如果我不知道将有多少表单,我将如何设置Knockout.js ViewModel?

我建议您可以通过ajax调用和绑定数据Knockout绑定以友好方式加载部分视图,如下所示:

//C# XxxController: return partial view:
public ActionResult MyView()
{
    return PartialView("_MyView");
}

//Ajax call to load partial view at client side:
$.get('Xxx/MyView', function(view){
    _contentHolder.html(view);
    ko.applyBinding(self, _contentHolder[0]);
})

您可以在模型集合中循环并动态应用淘汰绑定。

正如Anh Bui所建议的,我将在浏览器中动态创建它们。在服务器端使用ASP.net创建的标记使用
applyBindings
,这有点像黑客,意味着你要对抗淘汰,而不是使用淘汰

最好让Knockout负责实际创建表单。这意味着

  • 仅向其提供将每个表单创建为JSON所需的数据
  • 为表单标记创建淘汰模板
  • 使用
    forEach
    绑定在数据上循环
  • 模板:

    <script type="text/html" id="form-template">
      <form action="/target-url">
        <label for="user_name">What's your name?</label>
        <input type="text" data-bind="value: user_name" name="user_name" />
        <label for="user_location">Where are you from?</label>
        <input type="text" data-bind="value: user_location" name="user_location" />
      </form>
    </script>
    
    现在我们在视图模型上有了一个名为“forms”的observableArray,其中包含表单对象。我们使用
    forEach
    绑定生成尽可能多的表单,就像我们拥有表单对象一样:

    <div data-bind="template: { name: 'form-template', foreach: forms }"></div>
    
    如果愿意,可以在以下可运行代码段中尝试:

    var ViewModel=函数ViewModel(){
    var=这个,
    原始形式对象;
    //我们将JSON字符串重新构造为Javascript对象
    raw_forms_object=JSON.parse(来自_服务器的window.form_JSON_);
    //这就是从JSON生成的对象最终将在
    this.forms=ko.observearray([]);
    ko.utils.arrayForEach(原始形式对象,函数(f)){
    //f包含一个表单对象,例如
    //{用户名:“Foo1”,用户位置:“Bar1”}
    //我们创建了一个新对象,其中
    //属性是可观察的
    变量形式={
    用户名:ko.可观察(f.用户名),
    用户位置:ko.可观察(f.用户位置),
    };
    //将新表单对象添加到ObservalArray
    //确保使用“that”,因为“this”是范围
    //我们所处的每个回调的数组
    那。形成。推动(形成);
    });
    }
    应用绑定(新的ViewModel())
    
    
    你叫什么名字?
    你从哪里来的?
    window.form_json_from_server='[{“user_name”:“Foo1”,“user_location”:“Bar1”},{“user_name”:“Foo2”,“user_location”:“Bar2”},{“user_name”:“Foo3”,“user_location”:“Bar3”}];
    
    非常感谢您对该过程的高层解释!最后,我用Knockout映射插件处理ViewModel问题,使用
    var jsonData=@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model))技巧。我知道表单的呈现方式存在潜在的问题,而这个答案正是我需要的,以使模板更容易使用。它可以是div-dom:_-contentHolder=$(“#divContentHolder”)
    
    <script type="application/javascript">
      window.form_json_from_server = "[
    
       { user_name: "Foo1", user_location: "Bar1" },
       { user_name: "Foo2", user_location: "Bar2" },
       { user_name: "Foo3", user_location: "Bar3" }
    
      ]";
    </script>
    
    var ViewModel = function ViewModel() {
      var that = this,
          raw_forms_object;
    
      // we reconstitute our JSON string into a Javascript object
      raw_forms_object = JSON.parse(window.form_json_from_server);
    
      // this is where the objects made from our JSON will end up in
      this.forms = ko.observableArray([]);
    
      ko.utils.arrayForEach(raw_forms_object, function(f) {
        // f contains one of our form objects, such as { user_name: "Foo1", user_location: "Bar1" }
    
        // instead of adding f directly to the array, we make a new object in which the
        // properties are observables
        var form = {
          user_name: ko.observable(f.user_name),
          user_location: ko.observable(f.user_location),
        };
    
        // add our new form object to our observableArray
        // make sure to use 'that', because 'this' is the scope of the arrayForEach callback we're in
        that.forms.push(form);
      });
    }
    
    <div data-bind="template: { name: 'form-template', foreach: forms }"></div>
    
    ko.applyBindings( new ViewModel() );