javascriptjqueryasp.netjquery-widget-factory

jQuery Widget Factory access options in a callback method


I'm trying to create a jQuery control using the widget factory. The idea is that I turn a button into a jQuery button, give it an icon, and register the click event for that button such that when invoked, it displays a calendar control on a textbox, whose id is passed in as an option to the widget method:

$.widget("calendarButton", {
    options: {
        textFieldId: ''
    },
    _create: function () {
        this.element.button(
     {
         icons: {
             primary: "ui-icon-calendar"
         }
     }).click(function () {
         if (this.options.textFieldId != '') {
             $(this.options.textFieldId).datetimepicker('show');
             return false;
         }
     });
    }
});

The problem with this however, is that this.options is undefined when the click handler is invoked; which makes sense since the method has a different scope. So I tried to see if there is a way to define a "static" variable which then can be accessed inside the callback method. I found this answer that explained how to create variables inside a wrapper function like this:

(function ($) {

    var $options = this.options;

    $.widget("calendarButton", {
        options: {
            textFieldId: ''
        },
        _create: function () {
            this.element.button(
         {
             icons: {
                 primary: "ui-icon-calendar"
             }
         }).click(function () {
             if ($options.textFieldId != '') {
                 $($options.textFieldId).datetimepicker('show');
                 return false;
             }
         });
        }
    });
})(jQuery);

But it still reports that $options is undefined. Is there a way to achieve this? I'm trying to avoid requiring the callback function be passed in since it'll be pretty much the same for all instances. Any help is appreciated.


Solution

  • After playing with it for a few hours, I finally came across the jQuery Proxy method which is exactly what I was looking for. I changed the code a little bit to look like this:

    $.widget("calendarButton", {
        options: {
            textFieldId: ''
        },
        _create: function () {
            this.element.button(
             {
                 icons: {
                     primary: "ui-icon-calendar"
                 }
             }).on("click", $.proxy(this._clickHandler, this));
        },
        _clickHandler: function () {
            if (this.options.textFieldId != '') {
                $(this.options.textFieldId).datetimepicker('show');
            }
        }
    });
    

    Notice that instead of implementing the click callback directly, I'm essentially creating a delegate that points to my private _clickHandler function, which itself runs on the same context as the $.widget() method (since the second argument of $.proxy(this._clickHandler, this) returns $.widget()'s context) hence availablity of the options variable inside the method.