Security News
38% of CISOs Fear They’re Not Moving Fast Enough on AI
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
A KnockoutJS plugin that lets you track all changes within a view model seamlessly with the ability to pin point and process them on the fly. It does not require any modifications to the markup or view model itself which makes it ideal for testing and quick prototyping.
Usage:
ko.watch(targetObjectOrFunction, options, evaluatorCallback, context);
or
var property = ko.observable().watch(targetObjectOrFunction, options, evaluatorCallback, context);
targetObjectOrFunction
accepts any subscribable or function/object containing the targeted subscribables.
options
is only optional and can be replaced by evaluatorCallback
the response and evaluation function.
Deep Watcher:
The depth
option is used to limit the recursion depth. Its default value 1 limits it to a flat view model but a value of -1, as shown below, will
fully unleash it:
var viewModel = { ... };
ko.watch(viewModel, { depth: -1 }, function(parents, child, item) {
...
});
The callback function provides three arguments:
parents
: A list of all parents above the changed property.child
: The child property that changed.item
: Used to determine whether an array item has been added, moved or removed.Note that for observable arrays, subscriptions are created or destroyed on the fly as new items are added or removed.
To keep up with changes in the model structure itself however the mutable
option needs to be set to true
.
Auto Wrapper:
Setting the wrap
option to true
will make sure that all fields within the targeted object are wrapped within an observable even if new array items are added later on.
Chaining Support:
The chaining support provided adds in more ways to simplify the code and make it more readable. For example let's consider this simple view model:
var params = {
p1 = ko.observable(),
p2 = ko.observable(),
p3 = ko.observable()
}
To update a variable, say items
, whenever any parameter within params
changes we would most probably write something along those lines:
var items = ko.observableArray(); var items = ko.computed(function() {
ko.computed = function() { var p1 = self.params.p1();
var p1 = self.params.p1(); var p2 = self.params.p2();
var p2 = self.params.p2(); OR var p3 = self.params.p3();
var p3 = self.params.p3();
var newItems = ...;
var newItems = ...; return newItems;
self.items(newItems); }
}
However, using the plugin, we can just watch params
right away like so and let it do the rest:
var items = ko.observableArray(); var items = ko.observableArray();
ko.watch(params, function() { items.watch(params, function() {
var newItems = ...; OR var newItems = ...;
self.items(newItems); return newItems;
}); });
Finally adding a bit of fluency to the mix we end up with the single block below:
var items = ko.observableArray().watch(params, function() {
var newItems = ...;
return newItems;
});
Note that by omitting the target parameter we obtain a chainable version of .subscribe
.
So instead of creating a subscription separately like so:
var someProperty = ko.observable();
someProperty.subscribe(someFunction, options);
We can do away with the redundancy like so:
var someProperty = ko.observable().watch(someFunction, options);
Selective Subscription:
There are many ways we can go about making a selective watcher. Suppose we want to avoid watching the variable p3
.
To achieve this we could move p3
to another level like so:
var params = {
p1: ko.observable(),
p2: ko.observable(),
ignored: {
p3: ko.observable()
}
};
But this assumes that the depth option is set to 1. To avoid this we can pass in a new object made up of p1
and p2
only:
ko.watch({ 1: params.p1, 2: params.p2 }, function (parents, child, item) {
...
}
Or we can just use the hide
option this way:
ko.watch(this.params, { hide: params.p3 }, function (parents, child, item) {
...
}
The easiest way however is to simply tag p3
as non-watchable like so:
var params = {
p1: ko.observable(),
p2: ko.observable(),
p3: ko.observable().watch(false)
};
For more advanced cases however we can make use of the beforeWatch
option which gives us full control over the subscription process:
ko.watch(this.params, {
beforeWatch: function (parents, child) {
if (<some reason not to subscribe>)
return false; // cancel subscription
}
}, function (parents, child, item) {
...
});
Pausable Listener:
Pausing and resuming a reactor on any property can be done like so:
this.data.watch(false);
//...do work
this.data.watch(true);
Dispose/Unwatch:
The watch
function returns an object with a "dispose" method you can call to dispose the watch action:
var viewModel = { ... };
var res = ko.watch(viewModel, { depth: -1 }, function(parents, child, item) {
...
});
res.dispose();
Once disposed your model will be "unwatched"
Synchronous tracking: (since 1.4.0)
By default when new objects are added to the tree, they are automatically "watched" asynchronously (e.g: in a setTimeout) in order to keep the system more responsive.
Sometimes this behaviour is not "expected", so you can use the async: false
option to force watch to happen "inline".
Single notification for multiple array changes vs change by change notifications (since 1.4.0)
By default when items are moved in an array you receive 2 different notifications, the first will report the "deleted item" and the second one will report the "added item".
If you prefer to receive an array of items in a single notification you can use the splitArrayChanges: false
option. In that case you will receive an array of item instead of a single item even when there is only one item changed.
Projects using KO-Reactor:
As of now I'm only aware of this excellent undo manager by Stefano Bagnara:
https://github.com/bago/knockout-undomanager
Here's a Plunker showing it in action on an array within an array:
http://plnkr.co/edit/nB2129?p=preview
Reactor is also used (via Undomanager) in Mosaico the first opensource Email Template Editor:
https://github.com/voidlabs/mosaico
Do feel free to let me know if you have anything related to share and I'll gladly mention it here.
Further Notes:
Unlike ko.computed
no listeners are created for subcribables within the evaluator function.
So we no longer have to be concerned about creating unintended triggers as the code gets more complex.
Yet another usage not mentioned above example involves calling watch
on a function as shown below:
ko.watch(function() { ... }, options);
However it is nothing more than a cosmetic enhancement since it only returns a computed
of the function being passed in.
For an extensive list of available options please consult the param
sections of the source code.
In order to build and minify you can simply call grunt:
grunt
If you want a live rebuild for each changed
grunt develop
If you want to run the test suite:
grunt jasmine
If you want to generate the test runner in order to run the test suite in your browser
grunt jasmine:main:build
FAQs
KO-Reactor ===========
The npm package ko-reactor receives a total of 0 weekly downloads. As such, ko-reactor popularity was classified as not popular.
We found that ko-reactor demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.
Security News
Company News
Socket is joining TC54 to help develop standards for software supply chain security, contributing to the evolution of SBOMs, CycloneDX, and Package URL specifications.