简体   繁体   English

Knockout.js按钮点击更新ViewModel

[英]Knockout.js Update ViewModel on button click

Well, that's not the best situation description... Anyway, I'm trying to update my ViewModel but it's not working. 好吧,那不是最好的情况说明......无论如何,我正在尝试更新我的ViewModel,但它无法正常工作。 By default I'm getting data from controller function and by button click - from another function in same contoller, but ViewModel contain only data received after first ViewModel initialization. 默认情况下,我从控制器功能和按钮单击 - 从同一个控制器中的另一个函数获取数据,但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>

UPDATE. UPDATE。 I chaged block of code where I'm getting new data to be as follow: 我查了一段代码,我得到的新数据如下:

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

Unfortunately this is not working as well. 不幸的是,这不起作用。 Here is no any JS errors, controller return proper portion of updated data. 这里没有任何JS错误,控制器返回更新数据的适当部分。

I'm new to all of this, but if I'm reading your code correctly, you are calling the request function on a new instance of the view model and not the one that was bound to the html document. 我是所有这一切的新手,但如果我正确地阅读你的代码,你就是在视图模型的新实例上调用请求函数而不是绑定到html文档的实例。 You need to make the request call on the view model that you created after the initial get call completed. 您需要在初始get调用完成后创建的视图模型上进行请求调用。

Update: Sorry, I should have been more specific about the code I was referring to. 更新:对不起,我应该更具体地说明我所指的代码。 At the end of your code block you have the following code: 在代码块的末尾,您有以下代码:

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

In this code, it appears that each time the default button is clicked, a new view model is created and the request function is called on that view model. 在此代码中,似乎每次单击默认按钮时,都会创建一个新的视图模型,并在该视图模型上调用请求函数。

In the document ready function where you are defining what happens after the sales data is loaded, you have the following code which is what creates the view model that the html document is actually bound to: 在文档就绪功能中,您要定义加载销售数据后发生的事情,您可以使用以下代码创建html文档实际绑定到的视图模型:

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

Nothing ever calls the request function on this view model. 什么都没有在这个视图模型上调用请求函数。 I wonder if what you really want is to somehow bind the request function in this view model to the default button. 我想知道你真正想要的是以某种方式将此视图模型中的请求函数绑定到默认按钮。

I would try updating the viewmodel salesdata observable, by giving context: self and using the following success method: 我会尝试通过给出context: self并使用以下success方法来更新viewmodel salesdata observable:

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

EDIT: 编辑:

I can see you attached a click event with jQuery. 我可以看到你用jQuery附加了一个click事件。 You should use knockout clck binding instead: 您应该使用knockout clck绑定:

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

And in the viewmodel 并在viewmodel中

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

This way you can retrieve your viewmodel instead of creating a new one as you did with new viewModel().request(uri); 通过这种方式,您可以检索视图模型,而不是像使用new viewModel().request(uri);一样创建new viewModel().request(uri);

For more on click binding see http://knockoutjs.com/documentation/click-binding.html 有关点击绑定的更多信息,请访问http://knockoutjs.com/documentation/click-binding.html

Building slightly on the answer from @brader24 here: 稍微建立@ brader24的答案:

In your update button's click event, you use this line of code: 在更新按钮的click事件中,您使用以下代码行:

new viewModel().request(uri);

What that is doing is creating a new viewModel (separate from the one that you already have instantiated and have applied bindings for) and filling it's observable array with data via your request function. 这样做是创建一个新的 viewModel (与你已经实例化并已应用绑定的那个分开)并通过你的request函数用数据填充它的可观察数组。 It isn't affecting your original viewModel at all (the one that has it's bindings applied on the DOM!). 它根本不会影响你原来的viewModel (在DOM上应用它的绑定!)。 So you won't see any errors, but you also won't see anything happening on the page because all you did was create a new viewModel in memory, fill it with data, and do nothing with it. 所以你不会看到任何错误,但你也不会看到页面上发生任何事情,因为你所做的viewModel在内存中创建一个新的viewModel ,用数据填充它,并且不做任何事情。

Try this code (everything in your viewModel function looks fine). 试试这段代码( viewModel函数中的所有内容看起来都很好)。

$(document).ready(function () {
    var vm = new viewModel(); // declare (and instantiate) your view model variable outside the context of the $.ajax call so that we have access to it in the click binding
    $.ajax({
        url: "/api/sales",
        type: "GET",
        cache: false,
    }).done(function (data) {
        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;     
        vm.request(uri); // don't use a new instance of a view model - use the one you have already instantiated
    });
});

Using a Knockout click binding instead of attaching a click event handler using jQuery is usually the recommended route, but it is not necessary - so your existing code (with the modifications above) should work fine. 使用Knockout单击绑定而不是使用jQuery附加单击事件处理程序通常是推荐的路径,但这不是必需的 - 因此您的现有代码(具有上述修改)应该可以正常工作。 For more info on that, see Using unobtrusive event handlers in the Knockout docs 有关详细信息,请参阅Knockout文档中的使用不显眼的事件处理程序

Well. 好。 Final solution based on @GoTo answer is: Here is the way to call function in viewmodel via click databind. 基于@GoTo答案的最终解决方案是: 这是通过点击数据绑定在viewmodel中调用函数的方法。

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

Here is the function. 这是功能。 As you can see I'm calling self.salesdata instead of viewModel . 正如您所看到的,我正在调用self.salesdata而不是viewModel This solution is working fine but somehow now I have problem with data format that is binded this way - <td data-bind="text: moment($data.whensold).format('DD.MM', 'ru')"></td> . 这个解决方案工作正常但不知何故现在我遇到了以这种方式绑定的数据格式的问题 - <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);
                    });
                }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM