【问题标题】:Binding with multiple PartialViews in Knockout在 Knockout 中绑定多个 PartialView
【发布时间】:2015-01-17 08:57:23
【问题描述】:

我有一个 jQuery Accordion,每个面板都包含一个表单。所有表单都相同,输入共享相同的 ID、名称和data-bind 属性。

假设每个表单都有不同的绑定上下文(使用ko with:),如果有两个表单,则this is how I would set up the Knockout.js ViewModel

但是,我事先不知道会有多少表格。我正在为 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.

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

【问题讨论】:

    标签: asp.net-mvc knockout.js asp.net-mvc-5


    【解决方案1】:

    我建议您可以通过 ajax 调用动态加载局部视图并相应地绑定数据敲除绑定,如下所示:

    //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]);
    })
    

    您可以循环浏览您的模型集合并动态应用剔除绑定。

    【讨论】:

    • 可以是div dom:_contentHolder = $('#divContentHolder')
    【解决方案2】:

    正如 Anh Bui 所建议的,我会在浏览器中动态创建它们。将applyBindings 与您在服务器端使用 ASP.net 创建的标记一起使用有点像 hack,这意味着您要对抗 Knockout,而不是使用它。

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

    1. 仅向其提供创建每个 JSON 表单所需的数据
    2. 为表单标记创建 Knockout 模板
    3. 使用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>
    

    接下来,您将相关的表单数据输出为服务器端的 JSON 数组。我没用过ASP.net,所以这里只能给你伪代码:

    <script type="application/javascript">
      window.form_json_from_server = "
    
       @foreach (var form in Model.AllForms.ToList())
       {
         // .. ASP.net JSON output magic goes here
       }
    
      ";
    </script>
    

    这样你的标记的最终结果看起来像

    <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>
    

    (请注意,JS 字符串不能包含换行符,我这里用换行符格式化,方便阅读)

    现在我们将表单数据格式化为 JSON,保存在 Javascript 字符串中。接下来:您的 Knockout 视图模型:

    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);
      });
    }
    

    现在我们的视图模型上有一个名为“forms”的 observableArray,其中包含我们的表单对象。我们使用forEach 绑定来创建与表单对象一样多的表单:

    <div data-bind="template: { name: 'form-template', foreach: forms }"></div>
    

    剩下的就是将我们的视图模型实例应用到页面:

    ko.applyBindings( new ViewModel() );
    

    如果你喜欢,你可以在这个可运行的代码 sn-p 中尝试一下:

    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);
      });
    }
    
    
    ko.applyBindings( new ViewModel() );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    <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>
    
    <div data-bind="template: { name: 'form-template', foreach: forms }"></div>
    
    <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 jsonData = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model)); 技巧解决了 Knockout Mapping 插件的 ViewModel 问题。我知道我呈现表单的方式存在潜在问题,而这个答案正是我需要让模板变得更平易近人的原因。
    猜你喜欢
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 2013-07-25
    • 2017-08-08
    • 2013-07-18
    • 2015-02-27
    相关资源
    最近更新 更多