0

I have some sort of ViewCollection which renders all sub views.

define(
    ['jquery', 'underscore', 'backbone', 'text!templates/main/layout.html', 'text!templates/main/index.html', 'views/security/login', 'views/security/registration'], 
    function($, _, Backbone, LayoutTemplate, ContentTemplate, LoginView, RegistrationView) {

    var IndexView = Backbone.View.extend({

        tagName: "div",

        className: "container",

        template: LayoutTemplate,

        render: function() {
            this.$el.html(LayoutTemplate);

            this.$('div.content').html(ContentTemplate);
            this.$('div.sidebar').append(new LoginView().render().el);
            this.$('div.sidebar').append(new RegistrationView().render().el);

            return this;
        }

    });

    return IndexView;

});

This works quite good! Unfortunatly I have noticed that for example the LoginView can't handle events anymore.

define(
    ['jquery', 'underscore', 'backbone', 'text!templates/security/login.html'], 
    function($, _, Backbone, LoginTemplate){

    var LoginView = Backbone.View.extend({

        tagName: "form",

        className: "login well",

        template: LoginTemplate,

        events: {
            "submit form.login": "submit" 
        },

        render: function(){
            this.$el.html(this.template);

            return this;
        },

        submit: function(e){
            e.preventDefault();

            var credentials = {
                'username': $(e.target[1]).val()
                , 'password': $(e.target[2]).val()
            };

            console.log(JSON.stringify(credentials));

            $.ajax({
                url: '/session'
                , type: 'POST'
                , contentType: 'application/json'
                , data: JSON.stringify(credentials)
                , success: function() {
                    window.Router.navigate('node', { trigger: true });
                }
                , error: function(xhr, status, error) {
                    console.log([xhr, status, error]);
                    $(e.target[1]).closest('div.control-group').addClass('error');
                    $(e.target[2]).closest('div.control-group').addClass('error');
                }
            });
        }
    });

    return LoginView;

});

Instead of sending an ajax call the browser tries to submit the form data url-encoded as GET request that is a sign that the view doesn't listen on any views anymore...

Is there a option how I can rebind the view events to the element?

login.html

<fieldset>
    <legend>login</legend>
    <div class="control-group">
        <label class="control-label" for="_session_username">username:</label>
        <div class="controls">
            <input type="text" id="_session_username" name="session[username]" placeholder="george78" />
        </div>
    </div>
    <div class="control-group">
        <label class="control-label" for="_session_password">password:</label>
        <div class="controls">
            <input type="password" id="_session_password" name="session[password]" placeholder="••••••" />
        </div>
    </div>
    <button type="submit" class="btn btn-primary">login</button>
</fieldset>

the form tags are defined in the view also the .login class attribute.

bodokaiser
  • 15,122
  • 22
  • 97
  • 140
  • I don't see why the _submit event_ is not fired. Have you tried to debug a little bit?, putting a `console.log` into the `submit` function, for example. Also check the css selector `form.login` is actually correct. – fguillen Jul 25 '12 at 17:51
  • @fguillen yep, there is no console.log, classes are checked, the whole page reloads on submit because e.preventDefault(); doesn't get called (which is in the event function) – bodokaiser Jul 25 '12 at 18:06
  • So, that is now a bit wierd. I added a keyup event which seem to work. Only submit seems to be broken (the same with the registrationView) – bodokaiser Jul 25 '12 at 18:10
  • http://stackoverflow.com/questions/4909564/backbone-js-why-isnt-this-event-bound this means that this.el has to be explicity set in the view to work... But this would break my rendering? EDIT: same thing here: http://stackoverflow.com/questions/5624929/backbone-view-el-confusion/5757160#5757160. Events are bound to the el that is why submit doesn't work. But how do I fix this in my rendering? – bodokaiser Jul 25 '12 at 18:12
  • I still think is a _css selector_ problem. Try to reproduce the issue with very less code and upload it to jsFiddle. – fguillen Jul 25 '12 at 18:17
  • @fguillen this issue only appeared since I switched my rendering style... before this everything worked fine. Didn't change anything at the events. I also tried setting manuelly a jquery event listener in the console...worked – bodokaiser Jul 25 '12 at 18:20
  • check that there is not `form.login` element into your `LoginTemplate`, so there is not `form.login` into `LoginView.$el`. Actually there is not any `form` in the `LoginView.$el` context. – fguillen Jul 25 '12 at 18:20
  • @fguillen yeah that was actually the problem see the answer for more details – bodokaiser Jul 25 '12 at 18:28
  • 1
    I wasn't completely right: there was a `form` in your `LoginView.$el` and it was actually the `LoginView.$el` itself :) – fguillen Jul 25 '12 at 18:34

1 Answers1

1

I found the solution.

We have a scoping problem. Because I defined the form directly in the view (tagName: "form") the topest object is "form.login". But this we can't address through the selector anymore. We only can select child objects. (See Backbone internals).

Before:

    events: {
        'keyup form.login input': 'checkInput'
        , 'submit form.login': 'submit'
    },

After:

    events: {
        'keyup input': 'checkInput'
        , 'submit': 'submit'
    },
bodokaiser
  • 15,122
  • 22
  • 97
  • 140