How to handle events in jQuery UI widgets

I am trying to write a jQuery widget by model here . Here is a screenshot of the widget:

(function ($) { $.widget("ui.notification", { _create: function () { if (!this.element.hasClass("ntfn")) { this.element.addClass("ntfn"); } this.elTitle = this.element.append("<div class='ntfn-title'>Notifications</div>"); this.elTitle.click(this._titleClick) }, _titleClick: function () { console.log(this); } }); })(jQuery); 

The problem here is the "this" volume inside the _titleClick method, inside the method this points to the title element. But I need it to point to the widget element.

I think one way to do this would be to use a wrapper class like

 var that = this; this.elTitle.click(function() { that._titleClick.apply(that, arguments); }); 

Is this the best way to solve this problem, or is there a common template for solving this problem?

+6
javascript jquery jquery-ui
source share
7 answers

I wrote a method to solve this problem

 _wrapCallback : function(callback) { var scope = this; return function(eventObject) { callback.call(scope, this, eventObject); }; } 
+3
source share

Use the this._on() method to bind a handler. This method is provided by jQuery UI factory widgets and ensures that inside the handler function, this always refers to the widget instance.

 _create: function () { ... this._on(this.elTitle, { click: "_titleClick" // Note: function name must be passed as a string! }); }, _titleClick: function (event) { console.log(this); // 'this' is now the widget instance. }, 
+15
source share

You should look at jQuery.proxy () http://api.jquery.com/jQuery.proxy/

 el.bind('evenname', $.proxy(function () { this.isMyScope.doSomething(); }, scope)); 
+4
source share

In your create function (or somewhere in your instance) do the following:

  _create: function() { ... // Add events, you will notice a call to $.proxy in here. Without this, when using the 'this' // property in the callback we will get the object clicked, eg the tag holding the buttons image // rather than this widgets class instance, the $.proxy call says, use this objects context for the the 'this' // pointer in the event. Makes it super easy to call methods on this widget after the call. $('#some_tag_reference').click($.proxy(this._myevent, this)); ... }, 

Now define an object event handler as follows:

  _myevent: function(event) { // use the this ptr to access the instance of your widget this.options.whatever; }, 
+2
source share

define var scope = this and use the scope in the event handler.

  _create: function () { var scope = this; $(".btn-toggle", this.element).click(function () { var panel = $(this).closest(".panel"); $(this).toggleClass("collapsed"); var collapsed = $(this).is(".collapsed"); scope.showBrief(collapsed); }); }, 
0
source share

Another way to do the same without using closure is to pass the widget as part of the event data, for example:

 // using click in jQuery version 1.4.3+. var eventData = { 'widget': this }; // this will attach a data object to the event, // which is passed as the first param to the callback. this.elTitle.click(eventData, this._titleClick); // Then in your click function, you can retrieve it like so: _titleClick: function (evt) { // This will still equal the element. console.log(this); // But this will be the widget instance. console.log(evt.data.widget); }; 
0
source share

It used to be via jQuery bind now on .

As with jQuery 1.7, the .on () method is the preferred method for attaching event handlers to a document. For earlier versions, .bind () is used to bind the event handler directly to elements. Handlers are bound to the currently selected elements in the jQuery object, so these elements must exist at the to.bind () call point. For a more flexible event binding, see Discussion of event delegation in .on () or .delegate ().

 _create: function () { var that = this; ... elTitle.on("click", function (event) { event.widget = that; // dynamically assign a ref (not necessary) that._titleClick(event); }); }, _titleClick: function (event) { console.log(this); // 'this' now refers to the widget instance. console.log(event.widget); // so does event.widget (not necessary) console.log(event.target); // the original element `elTitle` }, 
0
source share

All Articles