1

I'm fairly new to JavaScript, and entirely new to Backbone.js.

In the code below, I am creating a new UserLocationModel and passing this model instance to a new UserLocationView object. In this view's initialize() I (try to) bound render() to any changes happening to the passed along model.

I'm fairly certain the model changes, I receive new latitude and longitude values from navigator.geolocation and I assign these values to the model's values. I also know that the view succesfully receives the model (this.model is never null).

Why is UserLocationView.render() not being called?

Model:

var UserLocationModel = Backbone.Model.extend({
    defaults: {
        latitude: -1,
        longitude: -1
    },

    updateLocation: function() {
        if(navigator.geolocation){
            navigator.geolocation.getCurrentPosition(this.positionSuccess, this.positionFailure);
                    }
    },

    positionSuccess: function(position) {
        this.set({ 
            latitude : position.coords.latitude,
            longitude : position.coords.longitude
        });
    },

    positionFailure: function() {
        ...
    }
});

View:

var UserLocationView = Backbone.View.extend({
    initialize: function(){
        _.bindAll(this,'render');
        if(this.model) this.model.on('change',this.render,this);
    },
    render: function(){
        console.log('UserLocationView render called.');
        ...
    }
});

Execution start:

window.MyApp = Backbone.View.extend({

    initialize: function() {
        userLocationModel = new UserLocationModel();
        userLocationView = new UserLocationView({ model: userLocationModel });
        userLocationModel.updateLocation();
        this.render();
    }
});

Edit:

I have rewritten some of the code above, to include model.set.

Edit 2: Additional information for moxn.

main.js:

define(['jquery', 'underscore', 'backbone','template', 'myapp'], function() {
    $(document).ready(function() {
        window.App = new MyApp({ appendTo: $('body') });
    });
});

called by this in the HTML:

<script data-main="../static/js/main" src="../static/js/vendor/require.js"></script>
Caroline
  • 920
  • 2
  • 8
  • 25

3 Answers3

0

In addition to using the set method suggested by Dennis Rongo, you need to make sure this is a model object when positionSuccess is invoked. So something like this:

updateLocation: function() {
    if(navigator.geolocation) {
        var self = this;
        navigator.geolocation.getCurrentPosition(function() { self.positionSuccess() },
                                                 function() { self.positionFailure() });
    }
},
Lyn Headley
  • 11,368
  • 3
  • 33
  • 35
0

The getCurrentPosition changes the context of this of that of the geolocation.

Try doing something like:

updateLocation: function() {
        if(navigator.geolocation)
            navigator.geolocation.getCurrentPosition(
              this.positionSuccess.call(this), 
              this.positionFailure.call(this));
    }, 
Dennis Rongo
  • 4,611
  • 1
  • 25
  • 25
0

I'm sure both Dennis' and Lyn's answers are valid as well, I just haven't been able to make them work.

What did work, is:

Approach A:

    updateLocation: function() {
        console.log('UserLocationModel.getLocation() called.');
        if(navigator.geolocation){
            navigator.geolocation.getCurrentPosition(_.bind(this.positionSuccess, this));
        }
    },

    positionSuccess: function(position) {
        this.set({ 
            latitude : position.coords.latitude,
            longitude : position.coords.longitude
        });
    },

Approach B:

    //in model
    initialize: function() {
        _.bindAll(this,'positionSuccess');
    },

More specifically, I'm using underscore.js' _.bind() or _.bindAll():

bind() Bind a function to an object, meaning that whenever the function is called, the value of this will be the object. Optionally, bind arguments to the function to pre-fill them, also known as partial application.

Your answers have given me the understandment to go look for and find that exact answer in Pass correct "this" context to setTimeout callback?

Community
  • 1
  • 1
Caroline
  • 920
  • 2
  • 8
  • 25