如何从bindingHandler中的ViewModel调用函数

时间:2014-10-28 15:22:29

标签: javascript knockout.js

我在viewModel中有一个方法,它调用ajax get方法来获取所有项目。这一切都很完美。然后我有一个ko.bindingHandler,用于通过ajaxSubmit内联上传图像。这也有效,但问题是我必须复制代码来获取上传图像的bindingHandler中的所有项目,否则图像一旦上传就不会更新。刷新页面可以解决问题,但我想让视图自动刷新新图像。所以真正的问题是可以从bindingHandler中的viewModel调用一个函数吗?任何帮助将不胜感激!

BindingHandler:

ko.bindingHandlers.imageInLineUpload = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var options = ko.utils.unwrapObservable(valueAccessor()),
            property = ko.utils.unwrapObservable(options.property);

        $(element).change(function () {
            if (element.files.length) {
                if ((element.files[0].type === "image/png") || (element.files[0].type === "image/jpeg")) {
                    var $this = $(this);
                    $(element.form).ajaxSubmit({
                        url: $.API.url + "XYZ",
                        type: "POST",
                        dataType: "text",
                        success: function (data) {
                            toastr.success('Upload Successful.');
                            var viewModel= new MyViewModel ();
                            viewModel.GetObjects();
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            toastr.error('Upload Failed. Please Try again!');
                        }
                    });
                }
                else {
                    toastr.error('Upload Failed. PNG and JPEG are the only supported formats.');
                }
            }
        });
    }
};

视图模型:

var MyViewModel = function () {     
   var self = this;     
   self.xyz = ko.observable("");    
   self.xyz  = ko.observable(""); 
   self.xyz = ko.observable("");

   self.GetObjects= function () {       
   // Ajax call to fetch objects.

   } 
   self.GetObjects();
};

ko.applyBindings(new MyViewModel ());

2 个答案:

答案 0 :(得分:1)

我过去使用的一种方法是将对函数的引用传递给绑定处理程序作为一个类似于我们在其他地方使用回调的选项 -

<div data-bind="imageInLineUpload: someObservable, imageILUOptions: { callback: myFunction }"></div>

并且在绑定处理程序中,您可以像这样访问函数 -

ko.bindingHandlers.imageInLineUpload = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var options = ko.utils.unwrapObservable(allBindingsAccessor).imageILUOptions;
        var callback = options.callback;

        // do something
        callback(someVar);

这允许您将任何函数传递给绑定并将其用作其内部的回调。它不是一个完美的解决方案,但应该能满足你的需求。

答案 1 :(得分:1)

有几种方法可以做到这一点。字面上“从绑定处理程序调用viewModel函数”的方法是:

var viewModel = ko.dataFor(element);
viewModel.GetObjects()

这会有效,但这是一个非常平庸的解决方案;它几乎将绑定处理程序紧密地耦合到这个特定的viewModel,它是一个隐式依赖项; bindingHandler API并不清楚需要此函数。


另一种方式(在我看来,更好的方法)是将函数作为options参数传递给bindingHandler:

<div data-bind="imageInLineUpload: {getImagesCallback: GetObjects}"></div>

在绑定处理程序中:

var options = ko.utils.unwrapObservable(valueAccessor()),
    getImagesCallback =  options.getImagesCallback;

getImagesCallback();

(这与PW Kad的答案类似,但我认为指定一个单独的bindingKey为不同的绑定处理程序提供选项对​​于必需的参数来说是一个坏主意,并且与仅仅通过相比,这是一种非常丑陋的方式来执行敲除绑定处理程序当前绑定程序的对象)


但实际上,如果您的绑定处理程序正在执行异步调用,我认为您需要重构某些内容。在我看来,绑定程序员应该只进行视图逻辑,而不是处理应该在ViewModel中的AJAX。