Search code examples
jqueryjquery-uioopjquery-ui-widget-factory

Have a jquery method call a jqueryui widget method


I have created a jQueryUI widget called "Picklist" using the widget factory. It works great. However, because it is a widget, it doesn't respond to the val() method.

I have a function that is looping through an array to assign data to web controls. For the most part, I can just use the jQuery method val() to assign the value. But that doesn't work for my widget.

I instead have to manually check if the widget exists on the control, and then call the widget version of val() to do the assignment. This seems terribly inefficient and the antithesis of good object oriented design.

    for (var i = 0; i < ControlData.length; i++)
    {
        var mapping = ControlData[i];
        $('#' + mapping.controlName).val(mapping.value);
        if ($('#' + mapping.controlName).data('Erik-Picklist'))
        {
            $('#' + mapping.controlName).Picklist("option", { val: mapping.value });
        }
    }

Is there a way to have val() map to a widget method on a certain element? I was thinking there might be a method I could call on the element that would map the val() method to the Picklist's val() method, but I haven't seen any example of that sort of thing.


Solution

  • Since no one responded, (That will teach me to post a question on a Friday evening) I spent a lot of time trying to figure out a way to do this. The best solution I could come up with was inspired by https://stackoverflow.com/a/5760684/594602

    Basically, override the existing val() function so that it checks for an override on the current element.

    $.fn.old_val = $.fn.val;
    $.fn.val = function ()
    {
        var ErikVal = this.data('ErikVal');
        if (ErikVal)
        {
            return ErikVal.apply(this, arguments);
        }
        else
        {
            return this.old_val.apply(this, arguments);
        }
    };
    

    In the _create() for the jQueryUI widget, I added the following:

    _create: function ()
    {
        ...
        this.element.data('ErikVal', function ()
        {
            this.Picklist("option", { val: arguments[0] });
        });
    },
    

    I'm not particularly proud of this, but it is working.