值没有绑定到knockout.js中的Ko.observable

时间:2017-02-28 06:12:44

标签: javascript jquery knockout.js knockout-mapping-plugin knockout-3.0

这是我用来绑定文本框的代码:

var CategoryViewModel = {
    categoryModel: ko.observable({
        categoryId: ko.observable(),
        categoryName: ko.observable(),
        active: ko.observable()
    }),
    GetCategoryById: function (data, event) {
        CategoryViewModel.ClickId(event.target.id);
        var ajaxUrl = ApplicationRootUrl("GetCategoryById", "Category") + "/" + CategoryViewModel.ClickId();

        $.ajax({
            type: "GET",
            contentType: "application/json; charset=utf-8",
            url: ajaxUrl,
            dataType: "json",
            success: function (data) {
                if (data.isSuccess) {
                    // This value got bind to textbox
                    CategoryViewModel.categoryModel(data.data);
                } 
            },
            error: function (err) {

            }
        });
    },
    CategoryAddButton: function() {
        CategoryViewModel.categoryModel();
        $('#addCategoryModel').modal('toggle');
    }            
};

$(document).ready(function () {
    ko.applyBindings(CategoryViewModel, document.getElementById("categoryMain"));
});

点击按钮时调用CategoryAddButton方法。我试图在此方法中清空模型值。

这是HTML:

<input type="text" name="CategoryName" class="form-control" placeholder="Enter Category Name" data-bind="textinput: categoryModel().categoryName">

文本框值在ajax调用上绑定。但是,在调用CategoryAddButton方法之后,该值不会绑定到文本框。

1 个答案:

答案 0 :(得分:3)

首先,我建议您使用不同的方法从您编写的内容创建视图模型。尽管一些初学者的例子也是如此,但这只是为了简单起见 - 实际上,将视图模型创建为对象文字往往不是一个好主意。这是因为在许多其他重复项中发布了hereherehere,访问同一对象的另一个属性可能会非常脏,尽管该任务应该是多么微不足道。

因此,为了解决这个问题,你应该使用构造函数和new运算符,因为这样可以更容易地操作对象。但是,我添加此内容仅作为编写更清晰代码的指南,使用构造函数和new对象语法不能单独解决问题。

让我们回到你的问题。要找出代码不起作用的原因,请查看绑定工作时如何操作数据以及何时不工作。

你说在AJAX调用成功后,值得到了正确的更新,因此绑定工作正常。这是因为在AJAX调用的success回调中,您实际上是将对象传递给categoryModel。但是,我会指出你传递给它的不是一个可观察但只是一个普通的对象,而你最初创建它的属性是可观察的!所以即使在那里你也可能遇到问题。

您还说过点击按钮后,该值未更新。我不确定你在这里想要达到什么目标;您想要显示什么以及数据来自何处?因为你编写了这行代码:

CategoryViewModel.categoryModel();

只是一个吸气剂 - 它不会以任何方式改变物体,你只是在读它的价值。没有实际修改它,当然什么都不会改变。

所以,我会给你一个实现整个事情的可能方法,我建议你阅读更多关于javascript对象构造函数以及如何使用它们正确使用knockout。

function categoryViewModel() {
    var self = this;

    // Don't wrap these in another observable, that's totally needless.
    this.categoryId = ko.observable(null);
    this.categoryName = ko.observable(null);
    this.active = ko.observable(true);

    // You could actually define this on the prototype
    // but I don't want to make it even more complicated
    this.GetCategoryById = function(categoryId) {
        // You could do this if the value passed can either be a plain value 
        // or an observable; ko will return the actual value to you.
        var catId = ko.utils.unwrapObservable(categoryId);

        var ajaxUrl = ApplicationRootUrl("GetCategoryById", "Category") + "/" + catId;

        $.ajax({
            type: 'GET',
            contentType: "application/json; charset=utf-8",
            url: ajaxUrl,
            dataType: "json",
            success: function(data) {
                if (data.isSuccess) {
                    // Correct the object references according to
                    // the structure of the response if needed.
                    self.categoryId(data.data.id);
                    self.categoryName(data.data.name);
                    self.active(data.data.isActive);
                }
            },
            error: function(err) {
            }
        });
    };

    this.CategoryAddButton = function() {
        self.categoryId(null);
        self.categoryName(null);
        self.isActive(true); // If you want to default to true.
        $('#addCategoryModel').modal('toggle');
    };
};

$(document).ready(function () {
    ko.applyBindings(new categoryViewModel(), document.getElementById("categoryMain"));
});

您的HTML可能是:

<input type="text" name="CategoryName" class="form-control" data-bind="textInput: categoryName" />

对于GetCategoryById函数,如果将其分配给函数原型,而不是为创建的每个对象分配“副本”,它甚至会更好。但是因为我假设你只有1个你的viewmodel实例,所以我现在认为它超出了范围。