4

How can i access click event outside the el scope.

What i have : HTML :

<div class="right_btn"></div>
<div id="template_loader">
    <!-- HTML template goes here which contain form inputs-->
    <input type="text" class="forgot_password_email" name="forgot_password_email"/>
</div>

View :

var ForgotPasswordView = Backbone.View.extend({
    el: "#template_loader",
    initialize: function () {
        console.log('Forgot Password View Initialized');
    },
    render: function () {
        blockPage();
        var that = this;  

        $.get(App.baseUrl + 'templates/forgot-password-view.html', function (data) {
            template = _.template(data, { });
            that.$el.html(template);
            unblockPage();
        }, 'html'); 
    },
    events:{
        'click .right_btn':'forgotPasswordSubmit', //Doesn't fire as its outside of el
    }, 
    forgotPasswordSubmit: function(e){
        alert($(".forgot_password_email").val());
        e.preventDefault();
    }
});

Ive gone through the following :

Backbone.js views - binding event to element outside of "el"

Howto bind a click event in a Backbone subview

but doesn't really help me get it to work.

How can i get the click event of .right_btn inside the view. I cannot change the template structure to include the right_btn inside theel. Is here anyway to bind the outside element or recognize the click event inside a backbone view itself.

Community
  • 1
  • 1
Roy M J
  • 6,926
  • 7
  • 51
  • 78
  • Possible duplicate of [Backbone.js views - binding event to element outside of "el"](http://stackoverflow.com/questions/8274257/backbone-js-views-binding-event-to-element-outside-of-el) – T J Jan 30 '16 at 04:16

3 Answers3

4

Unfortunately, there is no way of doing this using just the backbone library. Backbone expects the view to only handle the events within it's specific DOM element.

It would be best, if possible, to refactor your code so that you do not have to break these conventions. Blurring the boundary of a view can give you difficulty later on if you need to reposition the view and it has dependencies on it's parent environment.

If possible, create a parent view that contains the HTML you have listed above, and use that view to bind to the event and submit the form of it's child view.

If you have no choice but to do things this way, then I would advise using jQuery 'on' to bind to the event.

// Put this in your view to ensure that it is only bound when the form is
// added to the page. You could substitute 'on' for 'one' if you don't want
// the binding to maintain after the first submission.
var submitForm = function(){
  $('#template_loader form').submit();
};
$('.right_button').on('click', submitForm);
Khior
  • 1,244
  • 1
  • 10
  • 20
  • Actually there is a way.. Please see my answer.. I am not sure of the issues it has, but it served my purpose.. – Roy M J Nov 29 '13 at 16:21
  • Bringing the element to within the scope of the view is definitely a better solution than using jQuery to target it outside of scope. Just make sure you don't confuse yourself if you use differing root elements. – Khior Nov 29 '13 at 16:43
1

Actually there is a way :

The following is the original view which have a main template and inside the element template_loader, the forgotpassword template is renderer. The button right_btn is outside the elements scope and it did not fire.

var ForgotPasswordView = Backbone.View.extend({
    el: "#template_loader",
    initialize: function () {
        console.log('Forgot Password View Initialized');
    },
    render: function () {
        blockPage();
        var that = this;  

        $.get(App.baseUrl + 'templates/forgot-password-view.html', function (data) {
            template = _.template(data, { });
            that.$el.html(template);
            unblockPage();
        }, 'html'); 
    },
    events:{
        'click .right_btn':'forgotPasswordSubmit', //This will fire.
    }, 
    forgotPasswordSubmit: function(e){
        alert($(".forgot_password_email").val());
        e.preventDefault();
    }
});

So after a lot of research, i found a solution to my problem. Im not sure whether this has any drastic problems. I have not encountered anything yet and i will update this post if i find anything :

The idea to create a new instance for the same view, but this time with another el. By this way, we get to execute the initialize and render functions with the first el and use the next one for the events.

One downside is that you will not be able to use something like this to obtain first el peoperties. But since i am using jquery, i can use the selectors to get through this. Other than that, i did not find any issues... yet.!

new ForgotPasswordView ({
   el:'#master_template'
});
Roy M J
  • 6,926
  • 7
  • 51
  • 78
  • This changes the root element to include the right_btn within it's scope. This will work but you may as well remove `el: '#template_loader'` from the original View definition, as you are overriding it when you instantiate the ForgotPasswordView. – Khior Nov 29 '13 at 16:33
  • Yes, this i know. But i need that for the render function.. :).. Ive explained this in the answer.. I am not sure whether there are any other issues. The scope issue can be rectified by using jquery selectors.. Model can be declared once again before use, so that instead of using this.model, i can use like modelname.save().. – Roy M J Nov 29 '13 at 16:35
  • If you set the el upon initialization, then the render function will see `#master_template`, not `#template_loader`.. – Khior Nov 29 '13 at 16:38
  • Very strange.. But it is currently working fine for me..:(.. ill double check this.. – Roy M J Nov 29 '13 at 16:43
0

is your right_btn in another view?

you can do this by implementing a global event bus :)

see this answer for more details. Call a function in another Marionette.ItemView

Community
  • 1
  • 1
Yurui Zhang
  • 2,230
  • 16
  • 16
  • then you can bind a onclick event to it, or use anchor, in the dom: eg:
    – Yurui Zhang Nov 25 '13 at 14:23
  • Hi.. yes i tried to do that.. But it just gave jquery error.. Ive found another way of doing it.. May not be the proper way, but got it to work... – Roy M J Nov 29 '13 at 16:22