Backbone View: function is undefined

2019-08-27 02:34发布

I want to build a simple backbone app for depositing and withdrawing funds via Stripe. Since a lot of the functionality is common, I placed that in a Stripe view, and extend the Deposit and Withdraw views from it, like so:

var App = {
    Models: {},
    Collections: {},
    Views: {},
    Router: {}
}

App.Views.Home = Backbone.View.extend({
    el: $('#main-content'),

    template: Handlebars.compile($('#home-template').html()),

    render: function() {
        this.$el.html(this.template())
        return this
    },

    events: {
        'click #deposit-button': 'navigateToDeposit',
        'click #withdraw-button': 'navigateToWithdraw'
    },

    navigateToDeposit: function(e) {
        Backbone.history.navigate('/deposit', true)
    },

    navigateToWithdraw: function(e) {
        Backbone.history.navigate('/withdraw', true)
    }
})

App.Views.Stripe = Backbone.View.extend({
    el: $('#main-content'),

    initialize: function() {
        Stripe.setPublishableKey('pk_test_0QvQdPBkXAjB4EBsT4mf226x')
    },

    render: function() {
        this.$el.html(this.template())
        return this
    },

    events: {
        'click #submit': 'submitForm'
    },

    submitForm: function(e) {
        e.preventDefault()
        $('#submit').prop('disabled', true)
        var that = this
        Stripe.card.createToken($('#form'), that.stripeResponseHandler)
    },

    stripeResponseHandler: function(status, response) {
        var $form = $('#form')

        if(response.error) {
            $form.find('.payment-errors').text(response.error.message)
            $('submit').prop('disabled', false)
        } else {
            console.log(this)
            var form_data = this.getFormData(response.id),
                that = this
            $.post(that.transaction_endpoint, form_data, function(data, textStatus, jqXHR) {
                Backbone.history.navigate('/home', true)
            })
        }
    }
})

App.Views.Deposit = App.Views.Stripe.extend({

    template: Handlebars.compile($('#deposit-template').html()),

    getFormData: function(token) {
        return {
            amount: $('#form input[name=amount]').val(),
            token: token
        }
    },

    transaction_endpoint: 'handledeposit'
})

App.Views.Withdraw = App.Views.Stripe.extend({

    template: Handlebars.compile($('#withdraw-template').html()),

    getFormData: function(token) {
        return {
            name: $('#form input[name=name]').val(),
            email: $('#form input[name=email]').val(),
            token: token
        }
    },

    transaction_endpoint: 'handlewithdraw'
})

App.Router = Backbone.Router.extend({
    routes: {
        'deposit'   :       'showDepositView',
        'withdraw'  :       'showWithdrawView',
        '*path'     :       'showHomeView'
    },

    showDepositView: function() {
        var depositView = new App.Views.Deposit()
        depositView.render()
    },

    showWithdrawView: function() {
        var withdrawView = new App.Views.Withdraw()
        withdrawView.render()
    },

    showHomeView: function() {
        var homeView = new App.Views.Home()
        homeView.render()
    }
})

var router = new App.Router()

Backbone.history.start()

The call to the getFormData method gives me an error saying the function is undefined, even though I have defined it in both Deposit and Withdraw views. Also, I added a console.log(this) right above it, and it logs the Window object to the console instead of the View. What am I doing wrong here?

1条回答
虎瘦雄心在
2楼-- · 2019-08-27 02:43

I have a feeling it's to do with this call:

Stripe.card.createToken($('#form'), that.stripeResponseHandler)

Try binding this to the calling scope using .bind():

Stripe.card.createToken($('#form'), that.stripeResponseHandler.bind(this))

You don't really need to do var that = this but I'll leave it in for simplicity's sake.

查看更多
登录 后发表回答