1

Is there any kind of wildcard operator in the Durandal observable plugin, as there is in (for example) JsObservable?

The Durandal observable documentation gives this example:

var observable = require('plugins/observable');

var viewModel:{
    firstName:'',
    lastName:''
};

observable(viewModel, 'firstName').subscribe(function(value){
    console.log('First name changed.');
});

viewModel.firstName = 'Test';

What I'd like to do is use a wildcard to subscribe to any changed property on the target. Something like this:

observable(viewModel, '*').subscribe(function(property, value){
        console.log(property + ' changed.');
    });

I don't see anything in the API documentation, but wondered if there was anything undocumented, or if anyone has a workaround to implement this behaviour.

Jude Fisher
  • 11,138
  • 7
  • 48
  • 91

2 Answers2

1

Unfortunately, there is no wildcard operator for this functionality.

But you can easily create wrapper module for this functionality.

Here is small example:

var observable = require('plugins/observable');

var wildcardObservable = function(obj, changeCallback){
  for(var prop in obj){
    observable(obj, prop).subscribe(changeCallback);
  }
}

var changeCallback = function() {
  console.log('property changed.');
  }

Usage:

  var viewModel:{
    firstName:'',
    lastName:''
  };

wildcardObservable(viewModel, changeCallback);
Dmitry Zaets
  • 3,289
  • 1
  • 20
  • 33
  • But - it doesn't say which property has been modified, which makes its utility very limited. – Jude Fisher Apr 30 '14 at 18:40
  • You can also use this.target inside callback to get observable itself. But as far as I seen in sources of KnockoutJs there is no possibility to get name of Observable variable inside of subscribe function, only new value (it is passed as argument). – Dmitry Zaets May 05 '14 at 06:44
0

With thanks to U10 for the start above, (and with reference to a few examples on the web) I came up with the following, which uses a closure to track all the necessary properties. It's a bit messy but it does what I need for now - hopefully it will be of use to someone.

var ChangeTracker = (function () {
        function ChangeTracker() {
        }
        ChangeTracker.prototype._trackChange = function (prop, target) {
            var type = typeof (target[prop]);
            var value = target[prop];
            _logger.log("_trackChange", { target: target, prop: prop, type: type, value: value }, "CT");
            _obs(target, prop).subscribe(function (newValue) {
                var obj = {
                    target: target,
                    prop: prop,
                    newValue: newValue,
                    oldValue: value
                };
                _logger.log(">>>>>>>>>>>>>>> CHANGE!", obj, "CT");
                value = newValue;
            });
        };

        ChangeTracker.prototype.TrackChanges = function (target) {
            var _this = this;
            for (var prop in target) {
                if (target.hasOwnProperty(prop)) {
                    this._trackChange(prop, target);
                }
                var underlying = ko.utils.unwrapObservable(target[prop]);
                if (underlying instanceof Array) {
                    ko.utils.arrayForEach(underlying, function (item) {
                        _this.TrackChanges(item);
                    });
                } else if (typeof underlying === "object") {
                    this.TrackChanges(underlying);
                }                
            }
            }
        };
        return ChangeTracker;
    })();
Jude Fisher
  • 11,138
  • 7
  • 48
  • 91