dist/web-atoms-mvvm.js
function bindableProperty(target, key) {
    // property value
    var _val = this[key];
    var keyName = "_" + key;
    this[keyName] = _val;
    // property getter
    var getter = function () {
        // console.log(`Get: ${key} => ${_val}`);
        return this[keyName];
    };
    // property setter
    var setter = function (newVal) {
        // console.log(`Set: ${key} => ${newVal}`);
        // debugger;
        var oldValue = this[keyName];
        // tslint:disable-next-line:triple-equals
        if (oldValue == newVal) {
            return;
        }
        this[keyName] = newVal;
        var c = this._$_supressRefresh;
        if (!(c && c[key])) {
            Atom.refresh(this, key);
        }
        if (this.onPropertyChanged) {
            this.onPropertyChanged(key);
        }
    };
    // delete property
    if (delete this[key]) {
        // create new property with getter and setter
        Object.defineProperty(target, key, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true
        });
        // tslint:disable-next-line:no-string-literal
        if (target.constructor.prototype["get_atomParent"]) {
            target["get_" + key] = getter;
            target["set_" + key] = setter;
        }
    }
}
function bindableProperty(target, key) {
    // property value
    var _val = this[key];
    var keyName = "_" + key;
    this[keyName] = _val;
    // property getter
    var getter = function () {
        // console.log(`Get: ${key} => ${_val}`);
        return this[keyName];
    };
    // property setter
    var setter = function (newVal) {
        // console.log(`Set: ${key} => ${newVal}`);
        // debugger;
        var oldValue = this[keyName];
        // tslint:disable-next-line:triple-equals
        if (oldValue == newVal) {
            return;
        }
        this[keyName] = newVal;
        var c = this._$_supressRefresh;
        if (!(c && c[key])) {
            Atom.refresh(this, key);
        }
        if (this.onPropertyChanged) {
            this.onPropertyChanged(key);
        }
    };
    // delete property
    if (delete this[key]) {
        // create new property with getter and setter
        Object.defineProperty(target, key, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true
        });
        // tslint:disable-next-line:no-string-literal
        if (target.constructor.prototype["get_atomParent"]) {
            target["get_" + key] = getter;
            target["set_" + key] = setter;
        }
    }
}
function bindableProperty ( target , key ) { // property value var _val = this [ key ] ; var keyName = "_" + key ; this [ keyName ] = _val ; // property getter var getter = function ( ) { // console.log(`Get: ${key} => ${_val}`); return this [ keyName ] ; } ; // property setter var setter = function ( newVal ) { // console.log(`Set: ${key} => ${newVal}`); // debugger; var oldValue = this [ keyName ] ; // tslint:disable-next-line:triple-equals if ( oldValue == newVal ) { return ; } this [ keyName ] = newVal ; var c = this . _$_supressRefresh ; if ( ! ( c && c [ key ] ) ) { Atom . refresh ( this , key ) ; } if ( this . onPropertyChanged ) { this . onPropertyChanged ( key ) ; } } ; // delete property if ( delete this [ key ] ) { // create new property with getter and setter Object . defineProperty ( target , key , { get : getter , set : setter , enumerable : true , configurable : true } ) ; // tslint:disable-next-line:no-string-literal if ( target . constructor . prototype [ "get_atomParent" ] ) { target [ "get_" + key ] = getter ; target [ "set_" + key ] = setter ; } } }
This decorator will mark given property as bindable, it will define
getter and setter, and in the setter, it will refresh the property.

class Customer{

@bindableProperty
firstName:string;

}

@param {*} target
@param {string} key
This decorator will mark given property as bindable it will define getter and setter and in the setter it will refresh the property .