Knockout.js按钮点击更新ViewModel

时间:2014-04-25 12:37:21

标签: javascript jquery mvvm knockout.js

嗯,这不是最好的情况说明......无论如何,我试图更新我的ViewModel但它无法正常工作。默认情况下,我从控制器功能和按钮单击 - 从同一个控制器中的另一个函数获取数据,但ViewModel仅包含第一次ViewModel初始化后收到的数据。

<script>
     function viewModel () {
        var self = this;
        self.currentPage = ko.observable();
        self.pageSize = ko.observable(10);
        self.currentPageIndex = ko.observable(0);
        self.salesdata = ko.observableArray();
        self.newdata = ko.observable();
        self.currentPage = ko.computed(function () {
            var pagesize = parseInt(self.pageSize(), 10),
            startIndex = pagesize * self.currentPageIndex(),
            endIndex = startIndex + pagesize;
            return self.salesdata.slice(startIndex, endIndex);
        });
        self.nextPage = function () {
            if (((self.currentPageIndex() + 1) * self.pageSize()) < self.salesdata().length) {
                self.currentPageIndex(self.currentPageIndex() + 1);
            }
            else {
                self.currentPageIndex(0);
            }
        }
        self.previousPage = function () {
            if (self.currentPageIndex() > 0) {
                self.currentPageIndex(self.currentPageIndex() - 1);
            }
            else {
                self.currentPageIndex((Math.ceil(self.salesdata().length / self.pageSize())) - 1);
            }
        }
        //Here I'm trying to update ViewModel
        self.request = function (uri) {
            $.ajax({
                url: uri,
                contentType: 'application/json',
                data: [],
                type: 'GET',
                cache: false,
            success: function (data) {
                ko.mapping.fromJS(data.$values, {}, self.salesdata);
            }
            });
        }
    }
    $(document).ready(function () {
        $.ajax({
            url: "/api/sales",
            type: "GET",
            cache: false,
        }).done(function (data) {
            var vm = new viewModel();
            vm.salesdata(data.$values);
            ko.applyBindings(vm);
        }).error(function (xhr, status, error) {
            var err = eval("(" + xhr.responseText + ")");
            alert(err.Message);
        });
        //Here i'm calling for ViewModel update
        $(".btn-default").click(function () {
            days = $(this).val();
            var uri = "/api/sales?days=" + days;     
            new viewModel().request(uri);
        });
    });
</script>

更新 我查了一段代码,我得到的新数据如下:

self.request = function (uri) {
                $.getJSON(uri, function (data) {
                    ko.mapping.fromJS(data.$values, {}, viewModel);
                });
            }

不幸的是,这也行不通。这里没有任何JS错误,控制器返回更新数据的适当部分。

4 个答案:

答案 0 :(得分:6)

我是所有这一切的新手,但是如果我正确地读取你的代码,你就是在视图模型的新实例上调用请求函数而不是绑定到html文档的实例。您需要在初始get调用完成后创建的视图模型上进行请求调用。

更新: 对不起,我应该更具体地说明我所指的代码。在代码块的末尾,您有以下代码:

    $(".btn-default").click(function () {
        days = $(this).val();
        var uri = "/api/sales?days=" + days;     
        new viewModel().request(uri);
    });

在此代码中,似乎每次单击默认按钮时,都会创建一个新的视图模型,并在该视图模型上调用请求函数。

在文档就绪功能中,您要定义加载销售数据后会发生什么,您可以使用以下代码创建html文档实际绑定到的视图模型:

    var vm = new viewModel();
    vm.salesdata(data.$values);
    ko.applyBindings(vm);

此视图模型上没有调用请求函数。我想知道你真正想要的是以某种方式将此视图模型中的请求函数绑定到默认按钮。

答案 1 :(得分:5)

我会尝试更新viewmodel salesdata observable,方法是context: self并使用以下success方法:

self.request = function (uri) {
        $.ajax({
            url: uri,
            contentType: 'application/json',
            context: self,
            data: [],
            type: 'GET',
            cache: false,
        success: function (data) {
            this.salesdata(data.$values);
        }
        });
    }

修改

我可以看到你用jQuery附加了一个click事件。 您应该使用knockout clck绑定:

<button data-bind="click: clickEvent" value="1">Click me!</button>

在viewmodel中

clickEvent: function (data, event) { 
    days = event.target.value;
    var uri = "/api/sales?days=" + days;     
    data.request(uri);
}

通过这种方式,您可以检索视图模型而不是像new viewModel().request(uri);

那样创建新视图模型

有关点击绑定的更多信息,请参阅http://knockoutjs.com/documentation/click-binding.html

答案 2 :(得分:3)

稍微根据@ brader24的答案建立:

在更新按钮的click事件中,您使用以下代码行:

new viewModel().request(uri);

正在做的是创建一个 new viewModel(与您已经实例化并已应用绑定的那个分开)并通过{{填充它的可观察数组与数据1}}功能。它根本不会影响您的原始request(在DOM上应用绑定的那个!)。所以你不会看到任何错误,但你也不会看到页面上发生任何事情,因为你所做的只是在内存中创建一个新的viewModel,用数据填充它,并且不做任何事情。

尝试使用此代码(viewModel函数中的所有内容都可以正常使用)。

viewModel

使用Knockout单击绑定而不是使用jQuery附加单击事件处理程序通常是推荐的路径,但不是必需的 - 因此您的现有代码(具有上述修改)应该可以正常工作。有关详细信息,请参阅Knockout文档中的Using unobtrusive event handlers

答案 3 :(得分:0)

好。基于@GoTo答案的最终解决方案是: 以下是通过点击数据绑定在viewmodel中调用函数的方法。

<button type="button" class="btn btn-default" id="7" value="7" data-bind="click: getDays.bind($data, '7')">7</button>

这是函数。正如您所看到的,我正在调用 self.salesdata 而不是 viewModel 。这个解决方案工作正常但不知何故,现在我遇到了以这种方式绑定的数据格式的问题 - <td data-bind="text: moment($data.whensold).format('DD.MM', 'ru')"></td>

 self.getDays = function (days) {
                    var uri = "/api/sales?days=" + days;
                    $.getJSON(uri, function (data) {
                        ko.mapping.fromJS(data.$values, {}, self.salesdata);
                    });
                }