通过隐藏字段获得一个框架来处理knockout.js不持久化的问题

Getting a framework to deal with knockout.js not persisting via hidden field

本文关键字:knockout 处理 框架 js 不持久 问题 持久化 一个 字段 隐藏      更新时间:2023-09-26
  • VS2013,WebForms,.NET 4.51

我想使用一个隐藏字段来跨回发维护Knock-Out视图模型的内容。所以我从http://knockoutjs.com/examples/cartEditor.html然后阅读http://www.codeproject.com/Articles/153735/Using-KnockoutJS-in-your-ASP-NET-applications一些想法。

最终结果如下:

<asp:HiddenField ID="HiddenField1" runat="server" />
<script type='text/javascript' src="http://knockoutjs.com/examples/resources/sampleProductCategories.js"></script>
<script type="text/javascript">
    function formatCurrency(value) {
        return "$" + value.toFixed(2);
    }
    var CartLine = function () {
        var self = this;
        self.category = ko.observable();
        self.product = ko.observable();
        self.quantity = ko.observable(1);
        self.subtotal = ko.computed(function () {
            return self.product() ? self.product().price * parseInt("0" + self.quantity(), 10) : 0;
        });
        // Whenever the category changes, reset the product selection
        self.category.subscribe(function () {
            self.product(undefined);
        });
    };
    var Cart = function () {
        // Stores an array of lines, and from these, can work out the grandTotal
        var self = this;
        self.lines = ko.observableArray([new CartLine()]); // Put one line in by default
        self.grandTotal = ko.computed(function () {
            var total = 0;
            $.each(self.lines(), function () { total += this.subtotal() })
            return total;
        });
        // Operations
        self.addLine = function() {
            self.lines.push(new CartLine());
            SaveList();
        };
        self.removeLine = function(line) {
            self.lines.remove(line);
            SaveList();
        };
        self.save = function () {
            var dataToSave = $.map(self.lines(), function (line) {
                return line.product() ? {
                    productName: line.product().name,
                    quantity: line.quantity()
                } : undefined
            });
            alert("Could now send this to server: " + JSON.stringify(dataToSave));
        };
        self.SaveList = function () {
            var myHidden = document.getElementById('<%= HiddenField1.ClientID %>');
            if (myHidden)//checking whether it is found on DOM, but not necessary
            {
                var dataToSave = $.map(self.lines(), function (line) {
                    return line.product() ? {
                        productName: line.product().name,
                        quantity: line.quantity()
                    } : undefined;
                });
                alert("Saving - " + JSON.stringify(dataToSave));
                myHidden.value = JSON.stringify(dataToSave);
            }
        };
    };
    var stringViewModel = document.getElementById('<%=HiddenField1.ClientID %>').value;
    var viewModel;
    if (document.getElementById('<%=HiddenField1.ClientID %>').value == '') {
        alert('Nothing In Hidden Field');
        viewModel = new Cart();
    } else {
        viewModel = ko.utils.parseJson(stringViewModel);
        for (var propertyName in viewModel) {
            viewModel[propertyName] = ko.observable(viewModel[propertyName]);
        }
    }
    ko.applyBindings(viewModel);
    $(document.forms[0]).submit(function () {
        alert('In Submit');
        viewModel.SaveList();
    });
</script>

所以基本上,当页面加载时,我们会创建一个新的Cart实例。当表单发布后,我们成功地将购物车序列化到HiddenField1,我可以在后面的代码中看到预期值:

protected void btnSave_OnClick(object aSender, EventArgs aE)
{
    if (HiddenField1.Value == null)
    {
    }
}

但是,回发后stringViewModel的内容

var stringViewModel = document.getElementById('<%=HiddenField1.ClientID %>').value;

总是blanl/空的?为什么?

然后假设我有正确的JSON,下面是将其应用回视图模型的正确方法吗?

viewModel = ko.utils.parseJson(stringViewModel);
for (var propertyName in viewModel) {
    viewModel[propertyName] = ko.observable(viewModel[propertyName]);
}    

编辑:我尝试了一些没有运气的东西

  • 将所有JS代码添加到jQuert OnReady((处理程序
  • 尝试使用而不是ASP:HiddenField

在PostBack中的所有情况下,我都可以看到SaveList((为隐藏字段分配的值,但当页面再次显示时(回发后(,隐藏字段的值是一个空字符串

对于第一部分,您所做的是正确的。使用控制台(在浏览器中按F12(检查隐藏字段,并检查它是否具有值。如果您在服务器端看到它,那么它应该在客户端。您还可以运行js代码,并设置断点来发现问题所在。您还可以在服务器端添加PreRender处理程序,并添加断点和调试来检查服务器端是否没有删除Value(此事件发生在页面呈现为发送到浏览器之前(。

对于第二部分,最快的方法是使用敲除映射,它从JavaScript对象或JSON创建模型。您需要使用以下内容:ko.mapping.fromJSON。这将从JSON创建一个新的视图模型,您可以直接绑定它。(正如您在文档中所读到的,您可以自定义视图模型的创建方式(。

然而,你所做的却很奇怪。您通常将Knockout与Web API、Web服务或Page方法一起使用,而无需重新加载页面。模型是通过其中一种技术,使用AJAX来恢复、更新、更改等的。