Property changed decorator using ES7

Watching a model for changes is a pretty common requirement, and you often end up with code like this (in ES6):

export default class Foo extends EventEmitter {
    get bar() {
        return this._bar;
    }

    set bar(value) {
        if (value !== this._bar) {
            this._bar = value;
            this.emit("barChanged");
        }
    }
}

Boilerplate code is always an excuse for metaprogramming! And this seemed like an ideal use case for the proposed ES7 decorators.

We’re using babeljs via babelify, so needed to enable decorators in our gulpfile:

return browserify({
    ...
    transform: [babelify.configure({
        optional: ["es7.decorators"]
    })],
    ...
});

Once enabled, you can add the decorator:

export default class Foo extends EventEmitter {
    @propertyChanged
    get bar() {
        return this._bar;
    }

    set bar(value) {
        this._bar = value;
    }
}

function propertyChanged(target, name, descriptor) {
    let getter = descriptor.get, setter = descriptor.set;

    descriptor.set = function(value) {
        if (value !== getter.call(this)) {
            setter.call(this, value);
            this.emit(name + "Changed");
        }
    };

    return descriptor;
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s