1

I am trying to call a JQuery UI widgets 'custom' method and pass in the this/self/context for the purpose of testing. But the context isn't being passed to the method. When I inspect this from within the method its undefined.

The short example is I call the method using the following code:

widget.myWidget('option', "classChangeCallback").call(widget);

And when I inspect this from inside classChangeCallback it is undefined. Below is an example of the problem that you can replicate.

(function ($) {

  $.widget( "MY_NAMESPACE.myWidget", {

  	options: {

  		classChangeCallback: function() {
 
  			// When this callback is called via click evt: this.element is defined
  			// When this callback is called using .call, .apply: this.element is undefined
  			console.log(this.element);
			
			var newEle = $('<div><p>New Element</p></div>')
				.appendTo(this.element)

			return newEle;
		}
	},

	_create: function () {

		this._super( "_create" );

		// Bind to click event as an example only: in my project this 
		// callback is actually called when an elements classes change
		this.element.click(this.options.classChangeCallback.bind(this));
	},

  });

})(jQuery);



// .............

$(document).ready(function() {

	var widget = $('[data-type="foo"]').myWidget();

	// In my testing I want to call the function to test it
	widget.myWidget('option', "classChangeCallback").call(widget);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/>

<div data-type="foo" style="min-height:100px; background-color: green;">
		
		<p>
			Bar
		</p>
</div>

1
  • Does widget.myWidget('option', "classChangeCallback") return what you expect? Commented Jun 19, 2017 at 13:39

1 Answer 1

1

$(selector).myWidget() returns the jQuery object for chaining.

Therefore, in the line widget.myWidget('option', "classChangeCallback").call(widget);, you are passing a jQuery object as the context, not a widget instance as the member name suggests.

Although it's rather cumbersome, you could try :

widget.myWidget('option', "classChangeCallback").call(widget.myWidget("instance"));

But I can't help thinking that you might be better off establishing/triggering a custom event. As it says in the documentation,

The _on() method provides several benefits of direct event binding:

  • Maintains proper this context inside the handlers.
  • ...
  • Sign up to request clarification or add additional context in comments.

    Comments

    Your Answer

    By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.