4

I have many events bound to elements in my view, though when I use stickit js to change values in my view by altering the model it doesn't trigger an onChange event.

Is there a way that I can trigger an onchange event for the current model:element after the setting the value in the model without having to write a handler for every binding? This would be for all form elements, input/select/textarea.

I want to avoid the following for each form element on the page:

bindings: {
    '#foo': {
         observe: 'foo',
         afterUpdate: 'forceChange'
    },
    '#bar': {
         observe: 'bar',
         afterUpdate: 'forceChange'
    },
    ...
},

forceChange: function(el) { jQuery(el).change() }
ivory
  • 63
  • 1
  • 5
  • Trigger `onChange` of what? A DOM element? Why wouldn't your code just connect to the `change` event of the model? – WiredPrairie Mar 25 '13 at 10:52
  • You'll need to be more specific: when you say "it doesn't trigger an onChange event", what exactly are you doing? Are you (or the Stickit code) calling `yourModel.set(something)`? If so, is it calling it with the `silent` option, eg. `yourModel.set(something, {silent:true})`? If not, the change event will get triggered, so either you have another event handler blocking it, or the `set` isn't happening in the first place. – machineghost Mar 25 '13 at 20:19
  • Apologies for the ambiguity. When I call model.set('foo', 'bar') the DOM element that binds to that model item changes in value but does not trigger the onchange method. I have tried with jQuery('element').val('new value') and it also doesn't trigger a change event. I am not trying to trigger a model change event but rather a DOM element change event. – ivory Mar 25 '13 at 21:51

2 Answers2

5

One possible hack (with version 0.6.3 only) would be to define a global handler which matches all elements:

Backbone.Stickit.addHandler({
  selector: '*',
  afterUpdate: function($el) {
    $el.trigger('change');
  }
});

Since handlers are mixed in with other matching handlers and bindings configurations in the order that they are defined, you couldn't use afterUpdate in any of your bindings without overwriting this global, all-matching handler since the bindings configurations are the last to be mixed in. You can read more about it here.

user2095627
  • 362
  • 3
  • 7
  • Perfect, thanks. If I had enough rep, I would vote your answer up! Didn't think of the asterisk! – ivory Mar 26 '13 at 21:51
1

Ahhh, that comment clarifies matters. So, in Javascript when you change an input's value "manually" (whether through jQuery or through someElement.value =) the browser won't, as you noticed, fire a change event. Change events (and most other events for that matter) are only fired in response to user actions, not to Javascript.

Luckily, just as you can "manually" change a value, you can also "manually" trigger an event. In jQuery the syntax for that is:

$(yourElement).trigger('change');

If you need to control things like e.target you can read up on the jQuery trigger documentation for the details, but that's the basic idea.

You can even chain the value-changing and event-triggering together if you want:

$(yourElement).val('newValue').trigger('change');
machineghost
  • 33,529
  • 30
  • 159
  • 234
  • Thanks for your reply. I am hoping to globally invoke a change event on stickit update. As you can see in my example I am already using jQuery(el).change() which will invoke a change request just like jQuery(el).trigger('change'). Can stickit invoke a change request on my behalf rather than me having to put an 'afterUpdate' in each binding? – ivory Mar 26 '13 at 00:45