screenm0nkey
screenm0nkey

Reputation: 18795

dojo.dijit.Button fires onclick event twice

I'm instantiating a dijit button inside a custom widget. That bit all works fine. In widget code I'm binding an onclick event handler but when I click the button the event fires twice. Also a second issue is that it also binds the click event to other buttons in the page that aren't related to the widget. Below is a simplified version I what I have. Can anyone tell me why it's doing that. I've spent the last couple of hours trying to fix it.

The code is below but you can also see it here

This is the html page which instantiates the custom widget https://github.com/screenm0nkey/dojo/blob/master/widgets/destroy-widget.html

This is the custom widget https://github.com/screenm0nkey/dojo/blob/master/js/tag/widgets/DestroyWidget/Widget.js

This is the template which contains the nested widget https://github.com/screenm0nkey/dojo/blob/master/js/tag/widgets/DestroyWidget/templates/template.html

This is the html inside the widget template;

<div style="border: solid 1px pink">
<h3>${name}</h3>

<div dojoType="dijit.form.Button" data-dojo-attach-point="removeBtn" class="removeBtn">
  click me.
</div>

This is the JavaScript inside the widget which binds the handler;

define('tag/Widget', ['dojo', 'dojo/parser', 'dijit/_Widget', 'dijit/_TemplatedMixin'],

function(d, parser) {

return d.declare('tag.Widget', [dijit._Widget, dijit._TemplatedMixin], {

templateString : d.cache("tag", "/templates/template.html"),
widgetsInTemplate : true,
name : 'no name',
button : 'no button',

postCreate : function() {
  parser.parse(this.domNode);
  this.placeAt(d.byId('authorContainer'));
},

startup : function() {
  dijit.registry.forEach(dojo.hitch(this, function(w) {
    if (w.class === 'removeBtn') {
      this.button = w;
      return;
    }
  }))

  this.button.connect('onclick', function(evt) {
    console.log(evt.target);
  });
},

}); });

And this is the console output;

<input type="button" value="" class="dijitOffScreen" tabindex="-1" role="presentation" data-dojo-attach-point="valueNode">
<span class="dijitReset dijitInline dijitButtonText" id="dijit_form_Button_0_label" data-dojo-attach-point="containerNode">click me.</span>

Upvotes: 4

Views: 5977

Answers (4)

ptim
ptim

Reputation: 15587

I've been having this problem on a maintenance job..

I've ended up stopping event propagation:

clickFunction: function(e) {
    // business logic here...
    e.stopPropagation();
    window.event.cancelBubble = true; // IE
},

I believe my template (in jade, sorry) is correct:

button(data-dojo-type="dijit.form.ToggleButton",
       data-dojo-attach-event="onClick: clickFunction") Text

Works for me!

Upvotes: 0

neonstalwart
neonstalwart

Reputation: 770

use data-dojo-attach-event to automatically connect a handler for you.

in your javascript, add a function that you want to have called when the button is clicked:

// somewhere in your dojo.declare...
remove: function () {
    // do your remove stuff here
},

then in your template, you would have some markup like this:

<div data-dojo-type="dijit.form.Button" data-dojo-attach-event="onClick:remove">
    Remove
</div>

what that markup means is that you want to connect the onClick of the button to the remove function of the widget that owns that template.

as a bonus, the management of this connection is handled for you so you don't need to do anything to have it properly disconnected when your widget is destroyed. if you were to do the dojo.connect yourself then you should be storing a reference to the handle returned by dojo.connect and doing a dojo.disconnect when your widget is destroyed.

Upvotes: 1

hurrymaplelad
hurrymaplelad

Reputation: 27745

dijit.form.Button is dispatching the second click event on its internal button input. Check the source. I couldn't tell you why.

I'd recommend connecting to the widget's onClick event rather than the DOM event. missingno's answer describes the setup.

Upvotes: 1

hugomg
hugomg

Reputation: 69934

I don't know precisely why you get your problem but I think you might have avoided it if you used a more "Dojo style" way of doing things instead of your current "JQuery style" that uses classes for navigation:

  1. Try using the new data-dojo attributes instead of the old dojoType style:

    <div data-dojo-type="dijit.form.Button" class="remove">
    
  2. Use explicit attach points to reference inner widgets:

    <div data-dojo-type="dijit.form.Button"
         data-dojo-attach-point="removeBtn"            
         class="remove">
        Click me
    </div>
    
  3. The attach point will set a property of the main widget. You can access the button through it

    dojo.connect(this.removeBtn, ...
    
  4. Use onClick to connect to widgets instead of onclick

    dojo.connect(this.removeBtn, 'onClick', function(){ ... });
    

Upvotes: 5

Related Questions