0

I'm creating a re-usable object that would contain multiple properties. I would like to fire an event within the object that will update some of its own properties when a specific property is changed through assignment. I have read something similar to this but what they used was an object. How can I achieve this?

My apologies if this is something basic but I don't really have a formal training is JavaScript or in-dept knowledge how JavaScript works.

also I would like to add that this is something that should work in IE11 and up.

I have tested the method from this but unfortunately I don't really understand how can I implement it on my case.

Listening for variable changes in JavaScript

var test;

function myObject(){
  this.dataSource = null; 
  this.changeEvent = function(val){
    //do something inside
  }
}

test = new myObject();
test.dataSource = 'dataSource'; //trigger changeEvent() inside myObject
  • could you please provide more information? the js code you provided above should work. `//do something inside` you should add the properties that need to be changes in here. What is the object that needs to be changed? – A.J Alhorr Jun 10 '19 at 12:32
  • @A.JAlhorr lets just say I would like to do a console log when dataSource is changed via assignment – james castillo Jun 10 '19 at 12:35

4 Answers4

1

When creating the object, wrap it in a Proxy.

The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

Implement a set trap which performs the needed internal changes.

ThisIsNoZaku
  • 2,213
  • 2
  • 26
  • 37
0

You can store the value of dataSource in local storage and then compare and check if it has been changed.

var test;
function myObject()
{
  this.dataSource = null; 
  this.changeEvent = function(val)
  {
    console.log("Value has been changed.");
  }
}
test = new myObject();
test.dataSource = 'dataSource';
console.log("Before change" + test.dataSource);
localStorage.setItem("dataSource", test.dataSource);
var newVal = "dtSrc";
test.dataSource = newVal;
var originalVal = localStorage.getItem("dataSource");
console.log("After change" + test.dataSource);
if(newVal == originalVal)
    console.log("Value has not changed.");
else
    test.changeEvent();

Let me know if it works for you. If not, let me know the expected output.

Komal R
  • 387
  • 2
  • 16
0

OK, so I'll start from the method you've suggested and it seems you like that approach.

Sorry, if this seems obvious but better to explain!

Basically watch watches properties within your object (say datasource) and when a new value is assigned - fires the callback function. So, watch takes two params - what to watch, and what to do (when the property you are watching changes).

The caveat with this approach is it's a a non-standard and was not implemented by other browsers. Although, we can get a polyfill (which declares it if it does not exist).

https://gist.github.com/eligrey/384583

Warning from Mozilla's own docs:

Deprecation warning: Do not use watch() and unwatch()! These two methods were implemented only in Firefox prior to version 58, they're deprecated and removed in Firefox 58+. In addition, using watchpoints has a serious negative impact on performance, which is especially true when used on global objects, such as window. You can usually use setters and getters or proxies instead.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/watch

So, to implement using a polyfil of watch (thank Eli Grey for the Polyfill)

First, register the polyfill (put it somewhere which will run before anything else in JS, or put it in a polyfill.js file and import it first on your HTML page!)

/*
 * object.watch polyfill
 *
 * 2012-04-03
 *
 * By Eli Grey, http://eligrey.com
 * Public Domain.
 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 */

// object.watch
if (!Object.prototype.watch) {
    Object.defineProperty(Object.prototype, "watch", {
          enumerable: false
        , configurable: true
        , writable: false
        , value: function (prop, handler) {
            var
              oldval = this[prop]
            , newval = oldval
            , getter = function () {
                return newval;
            }
            , setter = function (val) {
                oldval = newval;
                return newval = handler.call(this, prop, oldval, val);
            }
            ;

            if (delete this[prop]) { // can't watch constants
                Object.defineProperty(this, prop, {
                      get: getter
                    , set: setter
                    , enumerable: true
                    , configurable: true
                });
            }
        }
    });
}

// object.unwatch
if (!Object.prototype.unwatch) {
    Object.defineProperty(Object.prototype, "unwatch", {
          enumerable: false
        , configurable: true
        , writable: false
        , value: function (prop) {
            var val = this[prop];
            delete this[prop]; // remove accessors
            this[prop] = val;
        }
    });
}

Then, to use (using your example);

var test;

**function myObject(){
  this.dataSource = null; 
  this.changeEvent = function (id, oldval, newval) {
    console.log(id + ' changed from ' + oldval + ' to ' + newval);
    return newval;
 }
  this.watch('datasource', this.changeEvent);
}**

test = new myObject();
test.dataSource = 'dataSource'; //trigger changeEvent() inside myObject

However, I would look into Event Listeners and trigger events when objects change - but that solution should work for you, especially with watch

Listening for variable changes in JavaScript

JRK
  • 3,686
  • 1
  • 13
  • 19
0

You can use like :

var myObject = {
    _dataSource: null,
    changeEvent : function(val){
        //do something inside
        alert(val);
    }
};
Object.defineProperty(myObject, "dataSource", {
    get: function(){
        return this._dataSource;
    }, 
    set: function(newValue){
        this._dataSource=newValue;
        this.changeEvent(this.dataSource);
    }
});

myObject.dataSource= "dataSource";
Ajay Kumar
  • 99
  • 6