varvet / serenade.js

Client side MVC framework
http://serenadejs.org
Other
524 stars 27 forks source link

Setters for properties is not documented #76

Open futuraprime opened 11 years ago

futuraprime commented 11 years ago

I can't figure out how to write a working setter for a property, and there is no documentation for how to do this.

If I have

@property 'foo',
    set : (value) ->
         console.log 'foo set to', value

The console statement shows up, but the value isn't set. I've tried returning value, calling super, setting the property in the setter (which triggers an infinite loop)—none of these work. Could you add an example setter function to your documentation or one of your examples?

jnicklas commented 11 years ago

This is actually surpisingly tricky (and stupid). We follow the convention set by Object.defineProperty, which is that there really is no convention. If you want to set a property, you need to do so yourself under a different name, and then make a getter that retrieves this property. We used to solve this by assigning the property on an object in attributes, so it would do something like this:

@property 'foo',
  get: -> @attributes.foo
  set: (value) -> @attributes.foo = value.toUpperCase()

If you're using Serenade 0.3.0 or earlier you can write a setter that assigns to @attributes.foo and the getter will just work. Expect this to break in the next release of Serenade though!

Unfortunately this does not play nicely with prototypal inheritance, so now we do something more like this:

@property 'foo',
  get: -> @_foo
  set: (value) -> @_foo = value.toUpperCase()

Note the underscore! The name of value we store this in is not a public API, so you should really define both getter and setter and choose a sensible name yourself.