不要使用Knockout发布SelectList

时间:2015-03-04 16:21:24

标签: asp.net asp.net-mvc-4 knockout.js knockout-mapping-plugin

我正在使用Knockout运行ASP.net MVC4应用程序。

我有一个发布我的Knockout表单的通用脚本。

我需要优化发送到服务器的数据,因为当我发布我的Knockout ViewModel时,所有项目的SelectList也会被发布!

示例服务器ViewModel:

Public Class FooViewModel Public Property Bar As String Public Property Products As List(Of SelectListItem) End Class

将我的Knockout ViewModel转换为JSON的JS代码

var data = ko.toJSON(viewModel);

数据变量包含所有产品项目,并且不是很优化。

我找到了这段代码(有效):

viewModel.toJSON = function () {
        var copy = ko.toJS(this);
        // remove any unneeded properties           
        delete copy.Products;            
        return copy;
    }

但我需要 通用 解决方案......!在这里,我不知道如何让它变得通用......

快速而肮脏的解决方案是在每个数组属性上添加后缀,例如" _NoPost"然后循环并删除具有此后缀的每个属性,但它闻起来......糟糕:/

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

一个选项是将表单数据与查找数据分开,如下所示。当您需要将表单数据发布到服务器时,这将允许您仅获取表单数据。

Public Class FormViewModel
     Public Property Bar As String
End Class

Public Class FooViewModel
     Public Property FormData As FormViewModel
     Public Property Products As List(Of SelectListItem)
End Class

这将允许你

var data = ko.toJSON(viewModel);
$post(url, data.FormData, function(d){...});

在HTML中,您还必须将FormData作为变量的一部分包括在内。

<input data-bind="value: FormData.Bar">

修改

根据您的反馈,您可以使用以下函数为您构建“干净”对象。我们的想法是传入原始的JSON对象以及一个映射对象,该对象将指示应该排除/遗留哪些属性:

function MapJson(obj, map) {

    if (obj == undefined)
        return;

    map = map || {};
    var ret = {};

    for (var prop in obj) {

        if (map[prop] != undefined && map[prop] == false)
            continue;

        if (typeof obj[prop] !== "object")
            ret[prop] = obj[prop];
        else {
            if (map.constructor == Array) {
                ret[prop] = MapJson(obj[prop], map[0]);
            }
            else
                ret[prop] = MapJson(obj[prop], map[prop]);
        }

    }

    return ret;
}

然后您可以像这样使用它 - 通过将属性的值设置为 false ,它将从数据中排除。该示例演示如何阻止子对象中的数组以及数组中的数组:

var obj = {
    Name: "John Doe",
    Vehicle: {
        Details: {
            Make: "Mazda",
            Model: 2010
        },
        Registration: "ABC123",
        ServiceDates: ["01 Jan", "23 Feb", "13 March"]
    },
    WeekDays: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    Children: [{ Name: "Mary", Age: 4, Hobbies: ["Soccer", "Chess", "Swim"] }, { Name: "Jane", Age: 2, Hobbies: ["Tennis", "Movies", "Reading"] }]
};

var map = {
    Vehicle: {
        ServiceDates: false
    },
    Children: [{
        Hobbies: false,
    }]
};

MapJson(obj, map);

希望它有所帮助。

编辑2

此处提供了一份基于您在评论中发布的数据的工作示例。

 var vm = {
    "Type":"PropertyTax",
    "Label":"d",
    "StartDate":"2015-01-01T00:00:00",
    "EndDate":"2015-12-31T00:00:00",
    "Value":0,
    "RegularizationMonth":0,
    "TotalConsumption":null,
    "UnitPrice":null,
    "Active":true,"Products":[{"Selected":false,"Text":"XXX 39","Value":"28"},{"Selected":false,"Text":"ZZZ","Value":"38"}],"ChargeProducts":[{"ProductID":"28","Products":[{"Selected":false,"Text":"XXX 39","Value":"28"},{"Selected":false,"Text":"XXX 41","Value":"8"}]}],
    "map":{"Products":false,"ChargeProducts":[{"Products":false}]}
    };

    var result = MapJson(vm, vm.map);

    console.log("Result: ", result);

答案 1 :(得分:0)

如果您使用KO.Mapping,则可以选择要忽略的某些部分。

            var mapping = { 'ignore': ["SomeFieldProperty"] };
            ko.mapping.fromJS(data, mapping, viewModel);

文档中的这一部分列出了操作绑定的所有方法,用于ko.mapping:

http://knockoutjs.com/documentation/plugins-mapping.html

向下滚动到底部,查看ignore上的位以及有关如何管理绑定和降级的主题。