0

How can I port this function to using the coffeescript class syntax?

App.PurchaseOrder = (uid) ->
  binder = new App.DataBinder(uid, "purchase-order")

  # Abstract all this out
  purchase_order =
    attributes: {}

    # The attribute setter publish changes using the DataBinder PubSub
    set: (attr_name, val) ->
      @attributes[attr_name] = val
      binder.trigger uid + ":change", [
        attr_name
        val
        this
      ]
      return

    get: (attr_name) ->
      @attributes[attr_name]

    _binder: binder

  # Subscribe to the PubSub
  binder.on uid + ":change", (evt, attr_name, new_val, initiator) ->
    purchase_order.set attr_name, new_val  if initiator isnt purchase_order
    return

  purchase_order

Something along the lines of this however this will not work because @attributes is not defined in the binder.on in the constructor.

class App.PurchaseOrder
  constructor: (@id) ->
    @binder = new App.DataBinder(@id, "purchase-order")
    @attributes = {}

    # Subscribe to the PubSub
    @binder.on @id + ":change", (evt, attr_name, new_val, initiator) ->
      @attributes.set attr_name, new_val  if initiator isnt @attributes
      return

  # The attribute setter publish changes using the DataBinder PubSub
  set: (attr_name, val) ->
    @attributes[attr_name] = val
    @binder.trigger @id + ":change", [
      attr_name
      val
      this
    ]
    return

  get: (attr_name) ->
    @attributes[attr_name]
3
  • Just curious - what is the goal here. The question is a little outside the scope of 'your' question, but I'm curious - for learning purposes - what you are doing here. Commented Nov 9, 2014 at 18:01
  • I have a rails app that I am trying to augment the ruby classes with js classes without the use of a client side framework. In this case I am setting up a convention that a client side purchase order model will be automatically bound to html elements that have specific data attributes. So if I have a page that has <td data-id="1" data-class="PurchaseOrder" data-attr="state">new</td> and I do purchase_order = new App.PurchaseOrder(1) then purchase_order.set("state", "pending") the html element will be updated. Commented Nov 9, 2014 at 19:08
  • 1
    It is a WIP but you can check out the source code here: github.com/mfpiccolo/happy_place_demo. and the demo here: happy-place-demo.herokuapp.com/purchase_orders. By entering the id in the input field you can edit the table directly. Commented Nov 9, 2014 at 21:05

2 Answers 2

1

If you do something like this

@binder.on @id + ":change", (evt, attr_name, new_val, initiator) ->
  @attributes.set attr_name, new_val  if initiator isnt @attributes
  return

then it means that this function will be invoked in global context or in the context of e.g. event object, but the point is that this may not point to the object you want. Instead of -> use =>

@binder.on @id + ":change", (evt, attr_name, new_val, initiator) =>
  @attributes.set attr_name, new_val  if initiator isnt @attributes
  return

then this inside the callback will be bound statically, in this example to the instance of your class.

Sign up to request clarification or add additional context in comments.

4 Comments

Small correction: I think the context of this in the event handler will be the event itself, not the global context.
@JedSchneider well, you may be right, all depends on how the callback is called. Updated the answer to be more precise on this.
The => is what I was looking for. Thank you. Do you think you could change the @attributes to this because I actually wanted to call set on the purchase order instance not the attributes object.
@mpiccolo Yes, you can use @set instead of @attributes.set here, if that's what you want.
0

how about this:

# Subscribe to the PubSub
@binder.on @id + ":change", ((evt, attr_name, new_val, initiator) -> 
    @attributes.set attr_name, new_val  if initiator isnt @attributes ).bind @
return

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.