4

I'm looking for ways to make the views independent. So, the events of a view are constrained to that view, not going into the elements of the children nor the parent.

The backbone.js framework binds the event on the top element of the view (view.el) using the jQuery .on method. As I have nested views, when I click on the button of view B, the event will be triggered on the view A also. I know that I can add a handler to the button click at view B and return false, but this way I need to know all events of the parent view and always handle all these events.

There follows an example of the problem: http://jsfiddle.net/57RAM/3/

I would like to click on MyViewB button and don't trigger the event of ViewA. I've tried adding 'all': -> return false in the events of view B, but it didn't worked.

Any suggestion?

msbrogli
  • 483
  • 3
  • 11
  • Why does it matter if the events propagate? There is no good way to catch all events - you can check if methods begin with 'on' like this http://stackoverflow.com/questions/5848598/how-can-i-bind-all-events-on-a-dom-element but that's about it. It would generally be considered bad architecture if you did this so I am wondering why. – Dominic Aug 05 '14 at 12:03
  • @DominicTobias This is just an example. I would like to have isolated views, but it doesn't seem to be simple. If the parent view has a button with class "submit", I would like to don't care if one of its children already has it. But it seems to matter and I guess it makes more complicated to create isolated views. – msbrogli Aug 13 '14 at 03:52
  • The only things that are properly isolated are Web Components – Dominic Aug 13 '14 at 07:52

2 Answers2

0

You could use ev.stopPropagation() in a click handler of the nested view (MyViewB) to prevent the event from bubbling up the DOM tree.

Patrick M
  • 166
  • 12
  • I know it but it doesn't solve my problem because I need to always handle all events of the parent view. As I want the view to be reusable and independent of its parent, it isn't a solution. – msbrogli Aug 05 '14 at 02:39
  • 2
    Could it be enough to just check if `evt.currentTarget === evt.target`? If false, it would indicate if the event is triggered as part of propagation and in this case you could ignore the event. – Patrick M Aug 05 '14 at 02:49
  • It seems a way to go, but I have to do this check in all event handlers and it isn't nice. – msbrogli Aug 05 '14 at 02:52
  • You're pretty much tied to how the DOM triggers and propagates events. I don't think you can really achieve decoupling of DOM events the way you seem to describe. What you could do instead is actually defining Backbone events for the events you care about and manage the propagation manually. So instead of listening to a click event on the parent view, you would listen to a Backbone event on the nested View. – Patrick M Aug 05 '14 at 02:56
0

If the problem is that view B must be reusable and if you don't mind that view A has knowledge of that, than you could use more specific event selectors for the view A bindings.

In the example a simple "button" selector is used, which will capture both buttons from view A and it's child view B. If a class, such as ".btn" or "button.view-a" is used it will prevent the issue.

The following snippet can be seen here using ".btn" to bind the event.

events:
    'click .btn': 'click'

click: (ev) ->
    alert('MyViewA button click')

initialize: ->
    $('<button class="btn">').text('MyViewA').appendTo(@el)
    child = new MyViewB
    $(child.el).appendTo(@el)
Jan Segre
  • 574
  • 5
  • 12
  • Yes, it will. I need to always use a prefix in the classes, like view-a:button. But it is not gonna work when I have a class A instance as a child of a class A instance (or in the descendants of a class A instance). – msbrogli Aug 05 '14 at 03:07
  • Apparently the events object may be a method, that way it may be dynamic, thus a possibility is to add an instance counter to ensure events are only bound only to the elements that were created on that instance. And that, although not much simple, works on the inheritance issue described. In practice: http://jsfiddle.net/57RAM/5/, notice that I created child element outside view A constructor to avoid an infinite loop. – Jan Segre Aug 05 '14 at 03:36