当从 knockout.mapping 创建可观察对象时,从数组中添加和删除对象

Add and remove object from array when the observable created from knockout.mapping

以下是我的代码的一个非常简化的版本..

我的html代码:

<div class="container body-content" data-bind="foreach:base">
    <div class="col-md-12" data-bind="with:s">
        <div class="col-md-4"><pre data-bind="text:sp"></pre></div>
        <div class="col-md-7">
            <div class="row" data-bind="foreach: spd">
                <input type="text" class="form-control" data-bind="value:value, valueUpdate: 'input'" />
                <button data-bind="click: $parent.addval">add</button><button data-bind="click: $parent.removeval">rem</button>
            </div>
        </div>
    </div>
</div>

我的Javascript代码:

<script src="knockout-3.2.0.js"></script>
            <script src="knockout.mapping.js"></script>
            <script>
                var data = [{
                    "s": {
                        "sp": "abc",
                        "spd": [
                          {
                              "value": ""
                          }
                        ]
                    },
                    "type": "xyz",
                 }];
                var AppScope = function () {

                    function BaseViewModel() {
                        var self = this;
                        self.base = ko.observableArray();
                        self.base(ko.mapping.fromJS(data)());
                    }
                    ko.applyBindings(new BaseViewModel());
                }();
            </script>

'data'数组来自服务器,数据结构复杂,$root不能使用。 使用的样式 here 可能是答案,但还无法弄清楚..

除按钮外,代码有效。我想了解如何将 {value:""} 对象添加到 'spd' 下的数组,并在按下 addval 和 remval 函数时将其删除。

真诚感谢所有帮助 谢谢

这是一种奇怪的设置,但我只是使用您提供的设置。 spd 最初有一个值为空的成员。输入框允许您更改值。 add 按钮将值复制到新条目中。 remove 按钮删除当前条目。

最棘手的一点是找出从 self.basespd observableArray 的结构。更新:我修改了点击绑定处理程序以获取 s 上下文(即 $parent),因此他们知道他们正在使用哪个 sspd

我将上下文从 $parent 更改为 $root 因为在 [=18= 处创建 addvalremoveval 函数对我来说没有意义]级。

var data = [{
  "s": {
    "sp": "abc",
    "spd": [{
      "value": ""
    }]
  },
  "type": "xyz",
}];
var AppScope = function() {

  function BaseViewModel() {
    var self = this;
    self.base = ko.observableArray();
    self.base(ko.mapping.fromJS(data)());
    self.addval = function(sData, data) {
      sData.spd.push({value: ko.observable(data.value())});
    };
    self.removeval = function(sData, data) {
      sData.spd.remove(data);
    }

  }
  ko.applyBindings(new BaseViewModel());
}();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div class="container body-content" data-bind="foreach:base">
  <div class="col-md-12" data-bind="with:s">
    <div class="col-md-4"><pre data-bind="text:sp"></pre>
    </div>
    <div class="col-md-7">
      <div class="row" data-bind="foreach: spd">
        <input type="text" class="form-control" data-bind="value:value, valueUpdate: 'input'" />
        <button data-bind="click: (data) => $root.addval($parent, data)">add</button>
        <button data-bind="click: (data) => $root.removeval($parent, data)">rem</button>
      </div>
    </div>
  </div>
</div>

如果您想使用不显眼的事件处理来做同样的事情(并且您有 jQuery),相关代码可能如下所示:

function BaseViewModel() {
    var self = this;
    self.base = ko.observableArray();
    self.base(ko.mapping.fromJS(data)());
  }
  ko.applyBindings(new BaseViewModel());

  $('body').on('click', '.add-btn', function() {
    const context = ko.contextFor(this);
    const data = ko.dataFor(this);
    const s = context.$parent;

    s.spd.push({
      value: ko.observable(data.value())
    });
  });

  $('body').on('click', '.remove-btn', function() {
    const context = ko.contextFor(this);
    const data = ko.dataFor(this);
    const s = context.$parent;

    s.spd.remove(data);
  });