【问题标题】:Knockoutjs mappings don't add observables to array of stringsKnockoutjs 映射不会将 observables 添加到字符串数组中
【发布时间】:2021-06-03 14:40:37
【问题描述】:

我正在从服务器获取此类数据

{
    FirmName: "Firm Name",
    Address: "123 Address",
    AltNames: [
        "First Alt Name",
      "Second Alt Name"
    ]
  }

我正在使用敲除映射插件将数据映射到带有 ko.mapping.fromJS(data, {}, this); 的 viewModel;

但是,每当我更改任何字符串数组元素时,我的更改都不会传播到 viewModel。我该怎么做才能解决这个问题?

我的js:

function firmModel() {
    //this is what I get from the server
  var data = {
    FirmName: "Firm Name",
    Address: "123 Address",
    AltNames: [
        "First Alt Name",
      "Second Alt Name"
    ]
  };
  
  ko.mapping.fromJS(data, {}, this);
  
}

var em = new firmModel();
ko.applyBindings(firmModel);

我的html:

<div>
  <label>Company</label>
  <input type="text" data-bind="value: FirmName">
</div>
<div>
  <label>Address</label>
  <input type="text" data-bind="value: Address">
</div>
<br>
<h3>
Alt Names
</h3>
<ul data-bind="foreach: AltNames">
  <li>
    <input type="text" data-bind="value: $data">
  </li>
</ul>

<br/><br/>
<h2>
Result of the changes where I see whether viewModel picks up my changes above
</h2> 
<span>Company: </span><span data-bind="text: FirmName"></span><br/>
<span>Address: </span><span data-bind="text: Address"></span><br/>
<br/>
Alt Names: <br/>
<ul data-bind="foreach: AltNames">
  <li data-bind="text: $data"></li>
</ul>

小提琴http://jsfiddle.net/n87esdLv/2/

【问题讨论】:

    标签: knockout.js knockout-mapping-plugin


    【解决方案1】:

    foreach 中不能使用$data

    <input type="text" data-bind="value: $data">
    

    正如您在documentation 中看到的那样:

    $原始数据

    这是当前上下文中的原始视图模型值。通常这与 $data 相同,但如果提供给 Knockout 的视图模型被包装在一个可观察对象中,则 $data 将是未包装的视图模型,而 $rawData 将成为 observable 本身

    那么,你需要改用$rawData,因为AltNames数组的内容必须是可观察的,而不是字符串。

    AltNames 中的字符串必须是可观察的。您需要使用custom object construction using “create”自定义AltNames数组的创建:

    var mapping = {
            'AltNames': {
                    create: function(options) {
                            return ko.observable(options.data);
                    }
            }
    }
    
    ko.mapping.fromJS(data, mapping, this);     
    

    这是一个可运行的示例:

    function firmModel() {
        //this is what I get from the server
      var data = {
        FirmName: "Firm Name",
        Address: "123 Address",
        AltNames: [
            "First Alt Name",
          "Second Alt Name"
        ]
      };
      
      //ko.mapping.fromJS(data, {}, this);
        var mapping = {
                'AltNames': {
                        create: function(options) {
                                return ko.observable(options.data);
                        }
                }
        }
    
      ko.mapping.fromJS(data, mapping, this);       
      
    }
    
    var em = new firmModel();
    ko.applyBindings(firmModel);
    h2{
      font-weight: bold;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
    <div>
      <label>Company</label>
      <input type="text" data-bind="value: FirmName">
    </div>
    <div>
      <label>Address</label>
      <input type="text" data-bind="value: Address">
    </div>
    <br>
    <h3>
    Alt Names
    </h3>
    <ul data-bind="foreach: AltNames">
      <li>
        <input type="text" data-bind="value: $rawData">
      </li>
    </ul>
    
    <br/><br/>
    <h2>
    Result of the changes
    </h2> 
    <span>Company: </span><span data-bind="text: FirmName"></span><br/>
    <span>Address: </span><span data-bind="text: Address"></span><br/>
    <br/>
    Alt Names: <br/>
    <ul data-bind="foreach: AltNames">
      <li data-bind="text: $data"></li>
    </ul>

    【讨论】:

    • 何塞,非常感谢!我有一个后续问题。如果 AltNames 不是根元素怎么办。例如,` {FirmNames: {MainName: "Bla", AltNames: ["One", "Two]}} ? I've tried using "FirmNames.AltNames": { create: function(options) { return ko.observable(options. data); } } ` 但它不起作用
    • 你能把这个字符串数组改成一个对象数组吗:{FirmNames: {MainName: "Bla", AltNames: [{name:"One"},{name: "Two}]}} 然后,插件将完成这项工作,而无需mapping。我在AltNames 中添加name:
    • 在这个小提琴jsfiddle.net/b2L3nmc5/3我使用相同的mapping,我认为它有效。
    • 谢谢你,何塞!你说得对。我需要在 ko 循环中使用 $rawData 而不是 $data 。再次感谢!
    猜你喜欢
    • 2015-06-22
    • 2012-01-23
    • 2023-03-23
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 2017-01-31
    • 1970-01-01
    相关资源
    最近更新 更多