Using Property Setters and Getters with Ext JS

by Shea Frederick on February 29th, 2012

Every once and a while I come across a bug where I need to go above and beyond the normal debugging norm to solve my problem.

My Bug

I had a boolean property on my column model that was getting set to the opposite of what I had initially set it to. Somewhere between the initial setting and it's reading back for column creation it was getting flipped from false to true. This is not a terribly uncommon thing to happen, but usually setting a few breakpoints at key locations in the code can find your problem. That wasn't working here.

I needed to find out exactly when the property got set and print out some info about where it happened. I had read about the new JavaScript setters and getters but never had a practical application to use them. This seemed a perfect fit.

Round #1 - Fight!

My first attempt looked something like this (I didn't look at any documentation, just typed from vague memory)...

Oh wow, that was an epic failure - "SyntaxError: Object literal may not have data and accessor property with the same name".

Round #2

Ok, let's just try that again, but remove the initial value and put that in the getter...

That worked, kinda. Trying to access the property however was not successful.

Error: "RangeError: Maximum call stack size exceeded"

Let's just step back for a second and talk about why this is recursive - I have setup a getter method for sortable that returns this.sortable which is in fact calling the getter method itself, hence the recursion. Now we can move on to what does work.

Round #3 - Win!

So now we have what I like to call the "I guess I should look at that documentation" moment, and after some other googling and reading of docs (linked at the end of this post) I found the correct usage along with the following quote that nicely sums up the problem I encountered on my first attempt:

...we have a new pitfall to avoid when iterating and cloning object properties, not to mention a significant risk of involuntary recursion...

Angus Croll

Yeah, thats me - Mr. Involuntary Recursion. Let's try that again, but this time well store our value in a different property so the name does not collide with the setter and getter thereby causing a recursive get or set.

Much better, that works as expected and now I can safely monitor a property for changes and do some debugging.

Here is what I ended up using as one of my column configs in my column model, using console.trace to get more details about the event.

This seemed like it should work, but didn't. The reason it didn't was due to the fact that the Ext JS library tries to break the referencing of objects by copying their properties over to a new object, and the method that does this could not differentiate between a property and a getter/setter method. A slight modification allowed it to make that distinction and voila!

The Magic

By copying the setter/getter over to the new object we are now able to monitor a property all of the way through the stack.

Enjoy!

The following are some references I found useful when figuring this stuff out.

2 Comments
  1. Defining implicit mutators [for debugging and logging] is a great idea. And I love the `magic` section for the Ext.apply issue… sounds like a need for an override or `monkey patch`.

    Thanks for the article.

  2. Murray permalink

    Hi Shea, thanks for this.

    I have just spent hours trying to debug a situation where a field in one specific record in a store was being mysteriously set to a specific value when another store loaded. After much console logging etc I found the problem code.

    However, what I wanted to do was watch that field and break when it changed to the foreign value, but I couldnt work out how. It was always at the same index in the store so I had a fixed variable to watch. ie: sAppTree.data.items[9].data.appmapdata.key

    So, my question is, could I have used a similar principle to yours to monitor that field and add a test and debugger; statement in the setter to stop as soon as the foreign value turned up? Could you point me in the right direction on how that might be done?

    Thanks again,
    Murray.
    PS: Thanks for your Learning ExtJS book – it really helped when I was starting with Ext, way back when…

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS