不要 post SelectList with Knockout

Do not post SelectList with Knockout

我是 运行 一个 ASP.net 具有 Knockout 的 MVC4 应用程序。

我有一个通用脚本,post是我的 Knockout Forms。

我需要优化发送到服务器的数据,因为当我 post 我的 Knockout ViewModel 时,包含所有项目的 SelectList 也被 post 编辑了!

示例服务器视图模型:

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);

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

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

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

但我需要一个通用解决方案...!在这里我看不出如何使它通用...

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

有什么想法吗?

一种选择是将表单数据与查找数据分开,如下所示。这将允许您在需要将表单数据 post 发送到服务器时只获取表单数据。

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">

编辑

根据您的反馈,您可以使用以下函数为您构建一个 "clean" 对象。这个想法是传入原始 JSON 对象以及一个映射对象,它将指示哪些属性应该 excluded/left 落后:

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

在此提供一个基于您在评论中 post 编辑的数据的工作示例。

 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);

如果您使用KO.Mapping,您可以选择忽略某些片段。

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

文档中的这一部分列出了您可以操纵绑定来来去去的所有方法,ko.mapping:

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

向下滚动到底部,查看 ignore 中的位以及涵盖如何管理绑定和解除绑定的主题。