将新的 Observable 添加到由 ko.mapping.fromJS 映射的 ObservableArray

Adding new Observable to ObservableArray mapped by ko.mapping.fromJS

本文关键字:mapping fromJS 映射 ko ObservableArray Observable 添加      更新时间:2023-09-26

我正在尝试将一个新的可观察数组添加到最初使用KO的映射插件映射的可观察数组中。但我不明白这一点。Firebug告诉我"TypeError:totalChf不是一个函数"。查看添加的可观察函数,我注意到没有创建计算函数。我已经尝试了几种方法,仍然没有成功...我错过了什么?

提前致谢

这里的代码:

var vm;
var ClientsMapping = {
  create: function (options) {
    var client = ko.mapping.fromJS(options.data, ContainersMapping)
    //Some computed observables for level one here...
    return client;
  }
}
var ContainersMapping = {
  'Containers': {
    create: function (options) {
      var container = ko.mapping.fromJS(options.data, MoneyAccountsMapping)
      container.totalChf = ko.computed(function () {
        var total = 0;
        $.each(container.MoneyAccounts(), function () {
          if (this.Currency() == "CHF") {
            total += this.Amount();
          }
        })
        return total;
      })
      //Some computed observables for level two here...
      return container;
    }
  }
}
var MoneyAccountsMapping = {
  'MoneyAccounts': {
    create: function (options) {
      var macc = new MoneyAccountModel(options.data)
      //Some computed observables for level three here...
      return macc;
    }
  }
}
var ClientModel = function (data) {
  ko.mapping.fromJS(data, {}, this);
}
var ContainerModel = function (data) {
  ko.mapping.fromJS(data, {}, this);
}
var MoneyAccountModel = function (data) {
  ko.mapping.fromJS(data, {}, this);
}
var data = [
  {
    'Clients': 'Thomas',
    'Containers': [
      {
        'ContName': 'Cont01',
        'MoneyAccounts': [
          { Currency: "CHF", Amount: 1000 },
        ]
      }
    ]
  },
{
  'Clients': 'Ann',
  'Containers': [
    {
      'ContName': 'Cont01',
      'MoneyAccounts': [
        { Currency: 'CHF', Amount: 1000 },
        { Currency: 'EUR', Amount: 500 }
      ]
    }
  ]
}
]
function viewModel() {
  var self = this;
  self.clients = ko.observableArray()
  self.clientsCount = ko.computed(function () {
    return self.clients().length
  })
}
$(function () {
  vm = new viewModel();
  vm.clients(ko.mapping.fromJS(data, ClientsMapping)());
  var cont1 = {
    'ContName': 'ContXX',
    'MoneyAccounts': [
      { Currency: "XXX", Amount: 1000 },
    ]
  };
  var cont2 = {
    'ContName': 'ContYY',
    'MoneyAccounts': [
      { Currency: "YYY", Amount: 1000 },
    ]
  };
  var cont3 = {
    'ContName': 'ContZZ',
    'MoneyAccounts': [
      { Currency: "ZZZ", Amount: 1000 },
    ]
  };
  var cont4 = {
    'ContName': 'ContWW',
    'MoneyAccounts': [
      { Currency: "WWW", Amount: 1000 },
    ]
  };
  vm.clients()[0].Containers.push(ko.mapping.fromJS(cont1, ContainersMapping));//Attempt1
  vm.clients()[0].Containers.push(ko.mapping.fromJS(cont2));//Attempt2
  vm.clients()[0].Containers.push(new ContainerModel(cont3));//Attempt3
  vm.clients()[0].Containers.push(ko.mapping.fromJS([cont4], ContainersMapping)()[0]);//Attempt4
  //...still no success.
})

您通常希望使映射彼此独立。执行此操作的一个好方法是在每个类中定义和执行映射:

var ClientModel = function(data) {
  var mapping = {
    'Containers': {
      create: function(options) {
        var container = new ContainerModel(options.data)
        //Some computed observables for level two here...
        return container;
      }
    }
  }
  ko.mapping.fromJS(data, mapping, this);
}

组织完后,您有几个选项可以将新项添加到 observableArray:

  1. 创建新项并将其推送到数组:

    vm.clients()[0].Containers.push(new ContainerModel(cont1))
    
  2. 在映射中指定一个键选项:

    var mapping = {
        'Containers': {
          key: function(item) {
            return ko.unwrap(item.ContName);
          },
          create: function(options) {
            var container = new ContainerModel(options.data)
            //Some computed observables for level two here...
            return container;
          }
        }
    }
    

    然后使用 mappedCreate 添加项目:

    vm.clients()[0].Containers.mappedCreate(cont1);
    

JSFiddle