0

I'm new at Backbone.js. So I want to ask a question about problem which I face with.

I have a User object which is exteded from Backbone.Model. According to the state of this object( authenticated or not), I want to change my views. I have showView method which enable my views to be rendered.

For this structure how I change my HomeView's template and enable it to be rendered according to the model. I think, just adding below code is not sufficient for this.

this.user.bind('change', this.render);

Any idea or help will be greately appreciated.

My Router

  var AppRouter = Backbone.Router.extend({
            routes: {
                '':'showHome',
                'join':'showJoin',
                'join/create':'showRegister',
                'join/complete':'showLoginComplete',
                 // Define some URL routes
                 //  'users': 'showContributors',
                 // Default
                ':actions': 'defaultAction'
            },
            showView: function(view) {
                if (this.currentView)
                {
                    this.currentView.close();
                    $('#tomato').attr("style",";display:none;");
                    $('#tomato').html(view.render().el);
                    $("#tomato").fadeIn("slow");
                }else{
                    $('#tomato').html(view.render().el);
                }
                this.currentView = view;
                return view;
            },
            login_required: function(callback) {
                if (this.user.get('is_authenticated')) {
                    if (callback) callback();
                } else {
                    //route login page...
                }
            },
            login_not_required:function(callback){
                if (this.user.get('is_authenticated')) {
                    //route 404 page...
                    this.navigate(':actions', true);
                } else {

                    if (callback) callback();
                }
            },
            updateUser:function(){
                var $self=this;
                $.get(
                    '/get_identity',
                    function(response){
                        // update model...
                        $self.user.id =response.identity;
                        //check user every five minutes...
                        $self.user.fetch({success: function() {
                           $self.user.set('is_authenticated',true);
                           setTimeout($self.updateUser, 1000*60*5);
                            }
                        },this);
                    }).fail(function(){
                        //clear model
                        $self.user.clear().set($self.user.defaults);
                    });
            }
        });

   var initialize = function(){

        //initialize user and it's checker.

        var app_router = new AppRouter;

        this.user = new User();
        _.bindAll(app_router, 'updateUser');
        app_router.updateUser();

        app_router.on('route:showHome', function(){
            var homeView = new HomeView({user:app_router.user});
            app_router.showView(homeView);
        });
 };
    return {
        initialize: initialize
    };

});

My HomeView

var HomeView = Backbone.View.extend({
        initialize:function(){
            this.user = this.options.user
        }
        render: function(){
            var headerView = new  HeaderView();
            var footerView = new FooterView();
            this.$el.append(headerView.render().$el);
            this.$el.append(homeTemplate);
            this.$el.append(footerView.render().$el);
            return this;
        }
    });
ibrahimyilmaz
  • 18,331
  • 13
  • 61
  • 80

3 Answers3

0

You are quite right but... First of all create View Class without explicit model object. And then create instance with object of your model

var homeView = new HomeView({
   model = user;
});

In initializing function of your View (remove this.user of course) with you should have this call

this.model.bind('change',this.render).
Damian0o
  • 653
  • 5
  • 15
  • 'this.model.bind('change',this.render).' only this is not sufficient. Because I need to do something which modify DOM element. – ibrahimyilmaz Mar 06 '13 at 09:55
  • In your render function you should also put values from your model to specific places. – Damian0o Mar 06 '13 at 10:03
  • Or you can use underscore templates [link](http://jsfiddle.net/derickbailey/Cpn3g/4/) or [link](http://backbonefu.com/2012/04/backbone-view-model-binding/) – Damian0o Mar 06 '13 at 10:05
  • Yes but this just return "el", I need to render this element. showView method has responsibility for rendering of view. So I need to find the way which trigger again showView or something which I don't know. – ibrahimyilmaz Mar 06 '13 at 10:06
  • I'm using underscore.js but my views create its el element and and return itself in render function. showView function takes this el and make it visible in HTML. – ibrahimyilmaz Mar 06 '13 at 10:08
  • Yes but you can also pass arguments to underscore template – Damian0o Mar 06 '13 at 10:13
0

I think your first guess of adding a listener to the model was right.

This is the way to do it.

In view:

this.listenTo(this.user, 'change', this.render);

Why do you think this is not the right way to do it?

Some frameworks like MarionetteJS do have a construct called Event Aggregator. It is kind of a Event bus you can listen to. My user for example sends events like 'user:login' on the bus. In the views i can listen on the bus.

pfried
  • 5,000
  • 2
  • 38
  • 71
  • My View rendered function is showView. This manipulates the Dom element as you can see. So just adding this piece of code is not required. So I need to find good way to do this. – ibrahimyilmaz Mar 06 '13 at 09:57
0

Here you have simple example of how it may works.

<html>
    <head>
        <script type="text/javascript" src="./public/js/jquery-1.9.1.min.js"></script>
        <script type="text/javascript" src="./public/js/json2.js"></script>
        <script type="text/javascript" src="./public/js/underscore-min.js"></script>
        <script type="text/javascript" src="./public/js/backbone-min.js"></script>

        <script type="text/javascript">

        var User = Backbone.Model.extend({
        defaults : {
       name : 'Damian0o',
       forum : 'stackoverflow'
    }

});


var MyView = Backbone.View.extend({

events: {
    "change input": "update"
},

initialize : function(){
    this.model.on('change',this.updateView,this);           
},

render : function(){
    this.$el.append('<input id="name" value="' + this.model.get('name') + '">');
    this.$el.append('<input id="forum" value="' + this.model.get('forum') +  '">');
},

update : function(){
    console.log(this.$el.find('input').val());
    this.model.set('name',this.$el.find('#name').val());
    this.model.set('forum',this.$el.find('#forum').val());
},

updateView : function(){
    this.$el.find('#name').val(this.model.get('name'));
    this.$el.find('#forum').val(this.model.get('forum'));
}

});


$(function(){


    var user = new User();

    var view = new MyView({
        model : user
    });

    var view2 = new MyView({
        model : user
    });

    view.render();
    view2.render();

    $('#div1').append(view.el);
    $('#div2').append(view2.el);

});

</script>

</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
</body>
</html>
Damian0o
  • 653
  • 5
  • 15