ObservableArray下的项目更新未传播到UI

时间:2014-03-30 19:14:21

标签: c# javascript jquery mvvm knockout.js

更新ObservableArrayItem而不更新Ui 我有如下的Knockout模型

我的c#数据模型看起来像这样

   public class DTO
    {       
        public decimal Amount { get; set; }
        public decimal AmountLeft { get; set; }      
        public TypeDTO[] BType { get; set; }
    }

       public class TypeDTO
    {
        public string Description { get; set; }
        public decimal Amount { get; set; }
    }

这是我的JS,对于初始加载它可以正常工作

var DetailsViewModel;

   $.ajax({
        url: "url",
        type: "get",
        contentType: "application/json",
        success: function (result) {

            for (i = 0; i < result.BType.length; i++) {
                addPercent(result.BType[i], result.Amount);
            }
            DetailsViewModel = ko.mapping.fromJS(result);
            ko.applyBindings(DetailsViewModel, $("#elem-box").get(0));


    });

function addPercent(BType, totalAmount)  //**adds two new fields to what server sends**
    {
        BType.Percent = ko.computed(function () {

            return ((BType.Amount / totalAmount) * 100).toFixed(2) + '%';
        });

        BType.Ratio = ko.computed(function () {

            return ((BType.Amount / totalAmount) ).toFixed(2);
        });

    }

在初始UI绑定上它完美运行。稍后当我在javascript中更新DetailsViewModel.BType中的数组时,它不会在UI中获得更新。

触发某些事件传递UI元素的索引对应于BType数组

var totalAmount = DetailsViewModel.Amount();

DetailsViewModel.BType()[index].Amount = totalAmount * 10;
DetailsViewModel.AmountLeft = totalAmount - DetailsViewModel.BType()[index].Amount;

addPercent(DetailsViewModel.BType()[index], totalAmount);

对于BType数组所做的更新都没有在UI端获得更新,也没有在addPercent函数下进行更新,在console.log上我可以看到所有在模型端执行的更新都成功运行。为什么arrayItem更新不会传播到UI?

2 个答案:

答案 0 :(得分:0)

您无法更新各个索引。您需要将整个数组传递给observable,以便knockout可以运行内部更新代码。

var bt = DetailsViewModel.BType();
bt[index].Amount = totalAmount * 10;
DetailsViewModel.BType(bt);

答案 1 :(得分:0)

@Robert Krzyzanowski所述之外,您还需要遵循以下模式:

var typeDTOs = ko.observableArray([]);
var underlyingArray = [];

_.each(result.BType, function(typeDTO) {
    typeDTO = addPercent(typeDTO, result.Amount);
    underlyingArray.push(typeDTO);
}

typeDTOs(underlyingArray);

或者那种效果(为了清楚起见,我在上面使用了underscore.js)。您希望确保不要进入 observable 数组;而是推入底层数组。然后,您可以一次更新可观察数组。如果你不这样做,你将最终为你推入可观察数组的每个项目触发更改事件 - 通常是不受欢迎的。

关于可观察数组的另一个注释

只是侧边栏...如果数组的元素是对象文字,并且您希望UI响应文字属性中的更改,则必须使每个UI绑定属性也是可观察的。