【问题标题】:Knockout.js - Updating an array in parent view model, with value in second view modelKnockout.js - 更新父视图模型中的数组,在第二个视图模型中具有值
【发布时间】:2015-04-15 08:30:19
【问题描述】:

所以我有 2 个视图模型,一个包含一个我使用的数组,它将dataList 中的每个数据节点绑定到表单,另一个用作每个数据节点的模型。我正在尝试使用第二个视图模型中的数据更新第一个视图模型中的数组:

HTML

<div data-bind="foreach:mainArray">
    <select data-bind="options: $root.ourTypes, optionsValue: 'ID', optionsText: 'Name', value: $data.OurTypeId"></select>
</div>

JavaScript

var dataList = [        
    { OurTypeId: 4 }, // there are other values here... 
    { OurTypeId: 2 }, // and here...
    { OurTypeId: 3 }  // and here...
];
var ourTypes = [
    { ID:"1", Name:"None", Limit:0 },
    { ID:"2", Name:"Fruits", Limit:5 },
    { ID:"3", Name:"Vegetables", Limit:5 },
    { ID:"4", Name:"Meats", Limit:2 }
];
var myViewModel = new MyViewModel(dataList);
ko.applyBindings(myViewModel);

function MyViewModel(dataList) {
    var self = this;
    self.ourTypes = ourTypes;
    self.mainArray = ko.observableArray([]);

    if (dataList.length > 0) {
        for (var i=0; i<dataList.length; i++) {
            var myDataViewModel = new MyDataViewModel(dataList[i]);
            //alert(myDataViewModel.OurType);
            self.mainArray.push(myDataViewModel);
        } 
    }
}

function MyDataViewModel(vm) {
    var self = this;
    if (vm != null) {                     
        var myType = "";
        for (var i=0; i<ourTypes.length; i++) {
            if (ourTypes[i].ID == vm.OurTypeId)
                myType = ourTypes[i].Name;
        }
        self.OurTypeId = ko.observable(vm.OurTypeId);
        self.OurType = myType;
   } else {
       self.OurTypeId = 0;    
       self.OurType = "";    
   }
   self.OurTypeId.subscribe(function(newValue) {
       var updatedItem = 0;
       var newName = "";
       for (var i=0; i<ourTypes.length; i++) {
          if (ourTypes[i].ID == newValue) {
            self.OurType = ourTypes[i].Name;
            // alert(ourTypes[i].Name);
             updatedItem = i;
          }
       }
   //  I want to do something like this to update "OurType" in mainArray...
   //  var theList = MyViewModel.mainArray();
   //  theList[updatedItem].OurType = self.OurType;
   //  MyViewModel.mainArray(theList);
   });
}

这实际上是代码的精简版本,只关注“ourTypes”,我的小提琴有更多。我使用下拉列表中的 ID 来指示模型的更改,但随后我必须手动更新类型的实际名称(当 ID 在我的小提琴中出现时,您将看到名称不会更新),所以我尝试在 .subscribe() 函数中执行此操作,但似乎没有任何效果。有什么想法吗?

小提琴:http://jsfiddle.net/navyjax2/ks6nbzp7/

【问题讨论】:

    标签: javascript arrays mvvm knockout.js viewmodel


    【解决方案1】:

    由于OurType 的名称应该会在您更改 ID 时自动更改,这对computed observable 来说是件好事:

    self.OurType = ko.computed(function() {
    
        return ko.utils.arrayFirst(ourTypes, function(type) {
            return type.ID == self.OurTypeId();
        }).Name;
    
    });
    

    当一个计算出的 observable 运行时,它会记录所有其他被访问的 observable——在我们这里的例子中,就是 self.OurTypeId()。这叫做依赖。每当依赖项发生变化时,都会自动再次运行计算。

    在这里,我们使用 Knockout 辅助函数 ko.utils.arrayFirst 迭代 ourTypes 并返回其中 ID 与用户选择的 self.OurTypeId() 匹配的第一个元素。然后我们返回 ourType 元素的 .Name

    JSFiddle

    请注意,您的 if (vm != null) else 子句可能存在问题:您在那里设置的值是不可观察的。

    self.OurTypeId = 0;
    

    这意味着MyDataViewModels(其中vmnull)将被破坏 - Knockout 会将&lt;select&gt; 绑定到一个普通的、不可观察的“0”,并且永远不会再次更新。

    另外,有一次您将 self.SlotPosition 设为 observable,另一次您将其设为 observableArray。

    最好将属性初始化为可观察一次,然后只更新它们的值:

    function MyDataViewModel(vm) {
        var self = this;
    
        this.SlotPosition = ko.observable();
        this.OurTypeId    = ko.observable();
    
        if (vm) {
            this.SlotPosition(vm.SlotPosition);
            this.OurTypeId(vm.OurTypeId);
        }
    
        this.OurType = ko.computed(function() {
    
            if (!self.OurTypeId()) {
                return;
            }
    
            return ko.utils.arrayFirst(ourTypes, function(type) {
                return type.ID == self.OurTypeId();
            }).Name;
    
        });
    }
    

    【讨论】:

    • 感谢您的回复 - 看起来很棒!为了解决您的其他问题,是的,我可能应该将 Id = 0 更改为 Id = 1。更多的只是证明如果我没有得到任何数据,我设置了一些默认值。
    • 很高兴听到这个消息!只是为了确保没有误解 - 问题不在于您将 id 设置为 0。问题在于您没有为它分配 observable。所以id = 0 是有问题的,而id = ko.observable(0) 本来可以的。但无论如何,它的结构方式更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    • 2014-01-03
    • 2014-10-04
    • 2013-08-26
    • 2017-05-04
    • 2017-08-28
    • 2017-09-01
    相关资源
    最近更新 更多