malcoauri
malcoauri

Reputation: 12199

JS message 'is not a function' in CoffeeScript

There is the following code:

class OrdersBySalonUpdater

    sendRequestToUpdateOrders: ->
        console.log('123')
        startDate = transformDate($("#from_datepicker"))
        endDate     = transformDate($("#to_datepicker"))
        businessId = $(".maininfo__datepickerwrap").attr("data-business-id")

        url = "some url"

        $.get url, (data) ->
            @updateOrders(data.orders)

    updateOrders: (orders) ->
        $("#salon_stat_table tr").slice(1).remove()
        $.each orders, (index) ->
            console.log(orders[index])

But when I execute the following:

    x = new OrdersBySalonUpdater()
    x.sendRequestToUpdateOrders()

I got the message "TypeError: this.updateOrders is not a function". How can I fix it? What's the problem? Thanks.

Upvotes: 0

Views: 144

Answers (1)

Alex P
Alex P

Reputation: 6072

In JavaScript, this is a context object. It can change, often when we don't want it to.

When you write @updateOrders(data.orders), CoffeeScript converts that to the JavaScript this.updateOrders(data.orders). However, you're calling updateOrders within a callback from jQuery's $.get. When your code gets executed, this no longer refers to your OrdersBySalonUpdater class - it's the context passed in the Ajax settings, or the settings themselves.


There's three ways we could solve this. The last is best - it's shortest, and the most idiomatic CoffeeScript.

  1. Store the current value of this, and use it within your callback. this can change, but if we store its current value in a variable then we can use it later. It's a common convention to call those variables that:

    sendRequestToUpdateOrders: ->
      that = this
      url = "some url"
    
      $.get url, (data) ->
        that.updateOrders(data.orders)
    
  2. Pass this into your callback as the context. jQuery lets us pass a context option to our Ajax methods. Whatever we pass will be available within the callback as this:

    sendRequestToUpdateOrders: ->
      url = "some url"
    
      $.get url, 
        success: (data) ->
          @updateOrders(data.orders)
        context: this
    
  3. Use the CoffeeScript fat-arrow to write your callback. The fat arrow defines a function and binds this for you:

    sendRequestToUpdateOrders: ->
      url = "some url"
    
      $.get url, (data) =>
        @updateOrders(data.orders)
    

Upvotes: 1

Related Questions