Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Vue methods from anonymous function

I'm just having a play with Vue.js (pretty new to javascript too) and trying to access the events in my Google calendar.

I keep getting 'undefined' when looking in the console.

    new Vue({
    el: '#app',
    data: {
        client_id: 'my_client_id',
        scopes: ["https://www.googleapis.com/auth/calendar.readonly"],
        events: {
            title: 'Upcoming Events',
            items: [],
        }
    },
    created: function () {
        this.loadCalendarApi();
    },
    methods: {
        addEvent: function (event) {
            this.events.items.push({
                title: event.summary,
                date: event.start.dateTime
            });
        },
        loadCalendarApi: function () {
            gapi.client.load('calendar', 'v3', this.listUpcomingEvents);
        },
        listUpcomingEvents: function () {
            var request = gapi.client.calendar.events.list({
                'calendarId': 'primary',
                'timeMin': (new Date()).toISOString(),
                'showDeleted': false,
                'singleEvents': true,
                'maxResults': 10,
                'orderBy': 'startTime'
            });
            var events = this.requestEvents(request);
            console.log(events);
        },
        requestEvents: function (request) {
            return request.execute(function (resp) {
                resp.items;
            });
        },
    },
});

I think the offending code is somewhere in the requestEvents method.

I also know that 'this.addEvent' is not in scope to be able to refer to the Vue object from inside the request.execute function but I don't know what I need to change.

Can anyone help me or let me know what I'm doing wrong?

Thanks!

like image 714
bencarter78 Avatar asked Jan 11 '16 19:01

bencarter78


2 Answers

Two ways you could do it, one would be to change execute(function) to execute(function, vue) and pass this in as the second argument. Then you could access it like so:

//update your execute function to pass along the vue variable into the response, then

requestEvents: function (request) {
        var events = request.execute(function (resp, vue) {
            for (i = 0; i < resp.items.length; i++) {
                vue.addEvent(resp.items[i]);
            }
        }, this);
        return events;
    }

Or if you have jQuery available, you can take a look at $.proxy() which alters a function to use the current context: https://api.jquery.com/jQuery.proxy/

requestEvents: function (request) {
        var events = request.execute($.proxy(function (resp) {
            for (i = 0; i < resp.items.length; i++) {
                this.addEvent(resp.items[i]);
            }
        }, this));
        return events;
    }

This way the anonymous response function will be run in the context of your Vue object.

Edit: I found this page as well which shows how you can bind the current context to a function using native JS, jQuery, or Underscore. Any of these would work: https://jsperf.com/bind-vs-jquery-proxy/5

like image 155
Jeff Avatar answered Sep 18 '22 00:09

Jeff


Nowadays you could use the request => {} notation instead of function(request) {} notation, which will pass on the context to the executing method so this.AddEvent() will work as expected.

like image 45
André Avatar answered Sep 22 '22 00:09

André