Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

knockout-decorators

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

knockout-decorators - npm Package Compare versions

Comparing version 0.7.1 to 0.8.0

43

dist/knockout-decorators.d.ts

@@ -17,5 +17,2 @@ /// <reference types="knockout" />

export declare function component(name: string, template: TemplateConfig, styles: string | string[], options?: Object): ComponentDecorator;
export interface Disposable {
dispose(): void;
}
/**

@@ -26,2 +23,10 @@ * Property decorator that creates hidden ko.observable with ES6 getter and setter for it

/**
* Accessor decorator that wraps ES6 getter to hidden ko.pureComputed
*
* Setter is not wrapped to hidden ko.pureComputed and stays unchanged
*
* But we can still extend getter @computed by extenders like { rateLimit: 500 }
*/
export declare function computed(prototype: Object, key: string | symbol, desc: PropertyDescriptor): PropertyDescriptor;
/**
* Property decorator that creates hidden ko.observableArray with ES6 getter and setter for it

@@ -40,16 +45,7 @@ */

destroyAll(items: T[]): void;
subscribe(callback: (val: T[]) => void): Disposable;
subscribe(callback: (val: T[]) => void, callbackTarget: any): Disposable;
subscribe(callback: (val: any[]) => void, callbackTarget: any, event: string): Disposable;
subscribe(callback: (val: T[]) => void): KnockoutSubscription;
subscribe(callback: (val: T[]) => void, callbackTarget: any): KnockoutSubscription;
subscribe(callback: (val: any[]) => void, callbackTarget: any, event: string): KnockoutSubscription;
}
/**
* Accessor decorator that wraps ES6 getter and setter to hidden ko.pureComputed
*/
export declare function computed(prototype: Object, key: string | symbol, desc: PropertyDescriptor): PropertyDescriptor;
/**
* Replace original method with factory that produces ko.computed from original method
*/
export declare function reaction(autoDispose: boolean): MethodDecorator;
export declare function reaction(prototype: Object, key: string | symbol, desc: PropertyDescriptor): PropertyDescriptor;
/**
* Apply extenders to decorated @observable

@@ -60,12 +56,2 @@ */

/**
* Subscribe to @observable by name or by specifying callback explicitely
*/
export declare function subscribe(callback: (value: any) => void, event?: string, autoDispose?: boolean): PropertyDecorator;
export declare function subscribe(targetOrCallback: string | symbol, event?: string, autoDispose?: boolean): PropertyDecorator;
export declare function subscribe(targetOrCallback: string | symbol, event?: string, autoDispose?: boolean): MethodDecorator;
/**
* Shorthand for ko.pureComputed(dependency).subscribe(callback)
*/
export declare function subscribe<T>(dependency: () => T, callback: (value: T) => void): KnockoutSubscription;
/**
* Like https://github.com/jayphelps/core-decorators.js @autobind but less smart and complex

@@ -76,2 +62,9 @@ * Do NOT use with ES6 inheritance!

/**
* Subscribe callback to dependency changes
*/
export declare function subscribe<T>(getDependency: () => T, callback: (value: T) => void, options?: {
once?: boolean;
event?: string;
}): KnockoutSubscription;
/**
* Get internal ko.observable() for object property decodated by @observable

@@ -78,0 +71,0 @@ */

@@ -53,67 +53,3 @@ (function (global, factory) {

}
var DECORATORS_KEY = typeof Symbol !== "undefined"
? Symbol("ko_decorators") : "__ko_decorators_";
var SUBSCRIPTIONS_KEY = typeof Symbol !== "undefined"
? Symbol("ko_decorators_subscriptions") : "__ko_decorators_subscriptions_";
var DISPOSABLE_KEY = typeof Symbol !== "undefined"
? Symbol("ko_decorators_disposable") : "__ko_decorators_disposable_";
var DecoratorType;
(function (DecoratorType) {
DecoratorType[DecoratorType["Extend"] = 0] = "Extend";
DecoratorType[DecoratorType["Subscribe"] = 1] = "Subscribe";
})(DecoratorType || (DecoratorType = {}));
function getMetaData(prototype) {
var metaData = prototype[DECORATORS_KEY];
if (!prototype.hasOwnProperty(DECORATORS_KEY)) {
prototype[DECORATORS_KEY] = metaData = assign({}, metaData);
objectForEach(metaData, function (key, decorators) {
metaData[key] = decorators.slice();
});
}
return metaData;
}
function getDecorators(metaData, key) {
return metaData[key] || (metaData[key] = []);
}
function getSubscriptions(instance) {
return instance[SUBSCRIPTIONS_KEY] || (instance[SUBSCRIPTIONS_KEY] = []);
}
function applyDecorators(instance, key, target) {
var metaData = instance[DECORATORS_KEY];
var decorators = metaData && metaData[key];
if (decorators) {
decorators.forEach(function (d) {
switch (d.type) {
case DecoratorType.Extend:
var extenders = d.value instanceof Function
? d.value.call(instance) : d.value;
target = target.extend(extenders);
break;
case DecoratorType.Subscribe:
var subscription = target.subscribe(d.value, instance, d.event);
if (d.dispose) {
getSubscriptions(instance).push(subscription);
}
break;
}
});
}
return target;
}
function redefineDispose(prototype) {
if (prototype[DISPOSABLE_KEY]) {
return;
}
prototype[DISPOSABLE_KEY] = true;
var original = prototype["dispose"];
prototype["dispose"] = function dispose() {
var disposables = this[SUBSCRIPTIONS_KEY];
if (disposables) {
disposables.forEach(function (s) { s.dispose(); });
}
if (original) {
return original.apply(this, arguments);
}
};
}
/*===========================================================================*/
/**

@@ -126,3 +62,3 @@ * Property decorator that creates hidden ko.observable with ES6 getter and setter for it

get: function () {
var observable$$1 = applyDecorators(this, key, ko.observable());
var observable$$1 = applyExtenders(this, key, ko.observable());
defProp(this, key, {

@@ -137,3 +73,3 @@ configurable: true,

set: function (value) {
var observable$$1 = applyDecorators(this, key, ko.observable());
var observable$$1 = applyExtenders(this, key, ko.observable());
defProp(this, key, {

@@ -149,6 +85,28 @@ configurable: true,

}
/*===========================================================================*/
/**
* Accessor decorator that wraps ES6 getter to hidden ko.pureComputed
*
* Setter is not wrapped to hidden ko.pureComputed and stays unchanged
*
* But we can still extend getter @computed by extenders like { rateLimit: 500 }
*/
function computed$1(prototype, key, desc) {
var _a = desc || (desc = getDescriptor(prototype, key)), get = _a.get, set = _a.set;
desc.get = function () {
var computed$$1 = applyExtenders(this, key, ko.pureComputed(get, this));
defProp(this, key, {
configurable: true,
get: computed$$1,
set: set
});
return computed$$1();
};
return desc;
// TODO: make @computed extendable (by @extend decorator)
}
var arrayMethods = ["pop", "push", "reverse", "shift", "sort", "splice", "unshift"];
var observableArrayMethods = ["remove", "removeAll", "destroy", "destroyAll", "replace", "subscribe"];
function defObservableArray(instance, key) {
var obsArray = applyDecorators(instance, key, ko.observableArray());
var obsArray = applyExtenders(instance, key, ko.observableArray());
var insideObsArray = false;

@@ -208,11 +166,12 @@ defProp(instance, key, {

}
function clearArrayMethods(array) {
arrayMethods.forEach(function (fnName) {
delete array[fnName];
});
observableArrayMethods.forEach(function (fnName) {
delete array[fnName];
});
}
}
// moved outside of defObservableArray function to prevent creation of unnecessary closure
function clearArrayMethods(array) {
arrayMethods.forEach(function (fnName) {
delete array[fnName];
});
observableArrayMethods.forEach(function (fnName) {
delete array[fnName];
});
}
/**

@@ -235,52 +194,31 @@ * Property decorator that creates hidden ko.observableArray with ES6 getter and setter for it

}
/**
* Accessor decorator that wraps ES6 getter and setter to hidden ko.pureComputed
*/
function computed$1(prototype, key, desc) {
var _a = desc || (desc = getDescriptor(prototype, key)), get = _a.get, set = _a.set;
desc.get = function () {
var computed$$1 = ko.pureComputed(get, this);
defProp(this, key, {
configurable: true,
get: computed$$1,
set: set
/*===========================================================================*/
var DECORATORS_KEY = typeof Symbol !== "undefined"
? Symbol("ko_decorators") : "__ko_decorators__";
function getOrCreateMetaData(prototype) {
var metaData = prototype[DECORATORS_KEY];
if (!prototype.hasOwnProperty(DECORATORS_KEY)) {
// clone MetaData from base class prototype
prototype[DECORATORS_KEY] = metaData = assign({}, metaData);
// clone extenders arrays for each property key
objectForEach(metaData, function (key, extenders) {
metaData[key] = extenders.slice();
});
return computed$$1();
};
return desc;
// TODO: make @computed extendable (by @extend decorator)
}
return metaData;
}
/**
* Replace original method with factory that produces ko.computed from original method
* @param autoDispose { Boolean } if true then subscription will be disposed when entire ViewModel is disposed
*/
function reaction(prototypeOrAutoDispose, key, desc) {
var autoDispose;
if (typeof prototypeOrAutoDispose === "boolean" && key === void 0) {
autoDispose = prototypeOrAutoDispose; // @reaction(false)
return decorator; // onSomethingChange() {}
function getOrCreateExtenders(metaData, key) {
return metaData[key] || (metaData[key] = []);
}
function applyExtenders(instance, key, target) {
var metaData = instance[DECORATORS_KEY];
var extenders = metaData && metaData[key];
if (extenders) {
extenders.forEach(function (extender) {
var koExtender = extender instanceof Function
? extender.call(instance) : extender;
target = target.extend(koExtender);
});
}
else if (typeof prototypeOrAutoDispose === "object" && key !== void 0) {
autoDispose = true; // @reaction
decorator(prototypeOrAutoDispose, key, desc); // onSomethingChange() {}
}
else {
throw new Error("Can not use @reaction decorator this way");
}
function decorator(prototype, key, desc) {
var value = (desc || (desc = getDescriptor(prototype, key))).value;
desc.value = function () {
var _this = this;
var args = slice(arguments);
var computed$$1 = ko.computed(function () { return value.apply(_this, args); });
if (autoDispose) {
getSubscriptions(this).push(computed$$1);
}
return computed$$1;
};
if (autoDispose) {
redefineDispose(prototype);
}
return desc;
}
return target;
}

@@ -293,60 +231,9 @@ /**

return function (prototype, key) {
getDecorators(getMetaData(prototype), key).push({
type: DecoratorType.Extend,
value: extendersOrFactory,
});
var medaData = getOrCreateMetaData(prototype);
var extenders = getOrCreateExtenders(medaData, key);
extenders.push(extendersOrFactory);
};
}
/*===========================================================================*/
/**
* Subscribe to @observable by name or by specifying callback explicitely
* @param targetOrCallback { String | Function } name of callback or callback itself
* when observable is decorated and name of observable property when callback is decorated
* @param event { String } Knockout subscription event name
* @param autoDispose { Boolean } if true then subscription will be disposed when entire ViewModel is disposed
*/
function subscribe(targetOrCallback, event, autoDispose) {
if (autoDispose === void 0) { autoDispose = true; }
if (typeof event === "function") {
// subscribe(() => this.observableField, (value) => { ... });
return ko.pureComputed(targetOrCallback).subscribe(event);
}
return function (prototype, key, desc) {
var _a = desc || (desc = getDescriptor(prototype, key)), value = _a.value, get = _a.get;
var targetKey;
var callback;
if (typeof value === "function") {
if (typeof targetOrCallback === "string" || typeof targetOrCallback === "symbol") {
targetKey = targetOrCallback; // @subscribe("target")
callback = value; // callback(value) {}
}
else {
throw new Error("Subscription target should be a key in decorated ViewModel");
}
}
else if (typeof get === "function") {
if (typeof targetOrCallback === "function") {
targetKey = key; // @subscribe(ViewModel.prototype.callback)
callback = targetOrCallback; // @observable target;
}
else if (typeof targetOrCallback === "string" || typeof targetOrCallback === "symbol") {
targetKey = key; // @subscribe("callback")
callback = prototype[targetOrCallback]; // @observable target;
}
else {
throw new Error("Subscription callback should be a function or key in decorated ViewModel");
}
}
getDecorators(getMetaData(prototype), targetKey).push({
type: DecoratorType.Subscribe,
value: callback,
event: event,
dispose: autoDispose,
});
if (autoDispose) {
redefineDispose(prototype);
}
return desc;
};
}
/**
* Like https://github.com/jayphelps/core-decorators.js @autobind but less smart and complex

@@ -373,3 +260,32 @@ * Do NOT use with ES6 inheritance!

}
/*===========================================================================*/
/**
* Subscribe callback to dependency changes
*/
function subscribe(getDependency, callback, options) {
var once = options && options.once || false;
var event = options && options.event || "change";
var dependency = ko.computed(getDependency);
var subscription = dependency.subscribe(callback, null, event);
var originalDispose = subscription.dispose;
// dispose hidden computed with subscription
subscription.dispose = function () {
originalDispose.call(this);
dependency.dispose();
};
if (once) {
dependency.subscribe(function () {
subscription.dispose();
});
}
return subscription;
}
/**
* Get internal ko.observable() for object property decodated by @observable
*/
function unwrap(instance, key) {
if (!hasOwnProperty(instance, key)) {
// invoke getter on instance.__proto__ that defines property on instance
instance[key];
}
return getDescriptor(instance, key).get;

@@ -380,8 +296,7 @@ }

exports.observable = observable$1;
exports.computed = computed$1;
exports.observableArray = observableArray$1;
exports.computed = computed$1;
exports.reaction = reaction;
exports.extend = extend;
exports.autobind = autobind;
exports.subscribe = subscribe;
exports.autobind = autobind;
exports.unwrap = unwrap;

@@ -388,0 +303,0 @@

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("knockout")):"function"==typeof define&&define.amd?define(["exports","knockout"],t):t(e.KnockoutDecorators=e.KnockoutDecorators||{},e.ko)}(this,function(e,t){"use strict";function o(e,o,n,r){return void 0===r&&(void 0===n?"object"!=typeof o||o.constructor!==Object||"require"in o||"element"in o||(r=o,o=void 0):"object"==typeof n&&(r=n,n=void 0)),function(n){t.components.register(e,g({viewModel:n.length<2?n:{createViewModel:function(e,t){var o=t.element,r=t.templateNodes;return new n(e,o,r)}},template:o||"<!---->",synchronous:!0},r))}}function n(e){var t=e[j];return e.hasOwnProperty(j)||(e[j]=t=g({},t),m(t,function(e,o){t[e]=o.slice()})),t}function r(e,t){return e[t]||(e[t]=[])}function i(e){return e[S]||(e[S]=[])}function u(e,t,o){var n=e[j],r=n&&n[t];return r&&r.forEach(function(t){switch(t.type){case h.Extend:var n=t.value instanceof Function?t.value.call(e):t.value;o=o.extend(n);break;case h.Subscribe:var r=o.subscribe(t.value,e,t.event);t.dispose&&i(e).push(r)}}),o}function c(e){if(!e[x]){e[x]=!0;var t=e.dispose;e.dispose=function(){var e=this[S];if(e&&e.forEach(function(e){e.dispose()}),t)return t.apply(this,arguments)}}}function s(e,o){_(e,o,{configurable:!0,get:function(){var e=u(this,o,t.observable());return _(this,o,{configurable:!0,enumerable:!0,get:e,set:e}),e()},set:function(e){var n=u(this,o,t.observable());_(this,o,{configurable:!0,enumerable:!0,get:n,set:n}),n(e)}})}function a(e,o){function n(e){A.forEach(function(t){return _(e,t,{configurable:!0,value:function(){if(c)return Array.prototype[t].apply(e,arguments);c=!0;var o=i[t].apply(i,arguments);return c=!1,o}})}),O.forEach(function(t){return _(e,t,{configurable:!0,value:function(){c=!0;var e=i[t].apply(i,arguments);return c=!1,e}})})}function r(e){A.forEach(function(t){delete e[t]}),O.forEach(function(t){delete e[t]})}var i=u(e,o,t.observableArray()),c=!1;_(e,o,{configurable:!0,enumerable:!0,get:i,set:function(e){var t=i.peek();t!==e&&(Array.isArray(t)&&w(t,"subscribe")&&r(t),Array.isArray(e)&&(w(e,"subscribe")&&(e=E(e)),n(e))),c=!0,i(e),c=!1}})}function f(e,t){_(e,t,{configurable:!0,get:function(){return a(this,t),this[t]=[],this[t]},set:function(e){a(this,t),this[t]=e}})}function l(e,o,n){var r=n||(n=k(e,o)),i=r.get,u=r.set;return n.get=function(){var e=t.pureComputed(i,this);return _(this,o,{configurable:!0,get:e,set:u}),e()},n}function b(e,o,n){function r(e,o,n){var r=(n||(n=k(e,o))).value;return n.value=function(){var e=this,o=E(arguments),n=t.computed(function(){return r.apply(e,o)});return u&&i(this).push(n),n},u&&c(e),n}var u;if("boolean"==typeof e&&void 0===o)return u=e,r;if("object"!=typeof e||void 0===o)throw new Error("Can not use @reaction decorator this way");u=!0,r(e,o,n)}function p(e){return function(t,o){r(n(t),o).push({type:h.Extend,value:e})}}function d(e,o,i){return void 0===i&&(i=!0),"function"==typeof o?t.pureComputed(e).subscribe(o):function(t,u,s){var a,f,l=s||(s=k(t,u)),b=l.value,p=l.get;if("function"==typeof b){if("string"!=typeof e&&"symbol"!=typeof e)throw new Error("Subscription target should be a key in decorated ViewModel");a=e,f=b}else if("function"==typeof p)if("function"==typeof e)a=u,f=e;else{if("string"!=typeof e&&"symbol"!=typeof e)throw new Error("Subscription callback should be a function or key in decorated ViewModel");a=u,f=t[e]}return r(n(t),a).push({type:h.Subscribe,value:f,event:o,dispose:i}),i&&c(t),s}}function y(e,t,o){var n=o||(o=k(e,t)),r=n.value,i=n.configurable,u=n.enumerable;return{configurable:i,enumerable:u,get:function(){if(this===e)return r;var o=r.bind(this);return _(this,t,{configurable:!0,value:o}),o}}}function v(e,t){return k(e,t).get}var h,g=t.utils.extend,m=t.utils.objectForEach,_=Object.defineProperty.bind(Object),k=Object.getOwnPropertyDescriptor.bind(Object),w=Function.prototype.call.bind(Object.prototype.hasOwnProperty),E=Function.prototype.call.bind(Array.prototype.slice),j="undefined"!=typeof Symbol?Symbol("ko_decorators"):"__ko_decorators_",S="undefined"!=typeof Symbol?Symbol("ko_decorators_subscriptions"):"__ko_decorators_subscriptions_",x="undefined"!=typeof Symbol?Symbol("ko_decorators_disposable"):"__ko_decorators_disposable_";!function(e){e[e.Extend=0]="Extend",e[e.Subscribe=1]="Subscribe"}(h||(h={}));var A=["pop","push","reverse","shift","sort","splice","unshift"],O=["remove","removeAll","destroy","destroyAll","replace","subscribe"];e.component=o,e.observable=s,e.observableArray=f,e.computed=l,e.reaction=b,e.extend=p,e.subscribe=d,e.autobind=y,e.unwrap=v,Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("knockout")):"function"==typeof define&&define.amd?define(["exports","knockout"],t):t(e.KnockoutDecorators=e.KnockoutDecorators||{},e.ko)}(this,function(e,t){"use strict";function n(e,n,r,o){return void 0===o&&(void 0===r?"object"!=typeof n||n.constructor!==Object||"require"in n||"element"in n||(o=n,n=void 0):"object"==typeof r&&(o=r,r=void 0)),function(r){t.components.register(e,v({viewModel:r.length<2?r:{createViewModel:function(e,t){var n=t.element,o=t.templateNodes;return new r(e,n,o)}},template:n||"<!---->",synchronous:!0},o))}}function r(e,n){y(e,n,{configurable:!0,get:function(){var e=f(this,n,t.observable());return y(this,n,{configurable:!0,enumerable:!0,get:e,set:e}),e()},set:function(e){var r=f(this,n,t.observable());y(this,n,{configurable:!0,enumerable:!0,get:r,set:r}),r(e)}})}function o(e,n,r){var o=r||(r=g(e,n)),i=o.get,u=o.set;return r.get=function(){var e=f(this,n,t.pureComputed(i,this));return y(this,n,{configurable:!0,get:e,set:u}),e()},r}function i(e,n){function r(e){k.forEach(function(t){return y(e,t,{configurable:!0,value:function(){if(i)return Array.prototype[t].apply(e,arguments);i=!0;var n=o[t].apply(o,arguments);return i=!1,n}})}),A.forEach(function(t){return y(e,t,{configurable:!0,value:function(){i=!0;var e=o[t].apply(o,arguments);return i=!1,e}})})}var o=f(e,n,t.observableArray()),i=!1;y(e,n,{configurable:!0,enumerable:!0,get:o,set:function(e){var t=o.peek();t!==e&&(Array.isArray(t)&&m(t,"subscribe")&&u(t),Array.isArray(e)&&(m(e,"subscribe")&&(e=j(e)),r(e))),i=!0,o(e),i=!1}})}function u(e){k.forEach(function(t){delete e[t]}),A.forEach(function(t){delete e[t]})}function c(e,t){y(e,t,{configurable:!0,get:function(){return i(this,t),this[t]=[],this[t]},set:function(e){i(this,t),this[t]=e}})}function s(e){var t=e[O];return e.hasOwnProperty(O)||(e[O]=t=v({},t),h(t,function(e,n){t[e]=n.slice()})),t}function a(e,t){return e[t]||(e[t]=[])}function f(e,t,n){var r=e[O],o=r&&r[t];return o&&o.forEach(function(t){var r=t instanceof Function?t.call(e):t;n=n.extend(r)}),n}function l(e){return function(t,n){var r=s(t),o=a(r,n);o.push(e)}}function b(e,t,n){var r=n||(n=g(e,t)),o=r.value,i=r.configurable,u=r.enumerable;return{configurable:i,enumerable:u,get:function(){if(this===e)return o;var n=o.bind(this);return y(this,t,{configurable:!0,value:n}),n}}}function p(e,n,r){var o=r&&r.once||!1,i=r&&r.event||"change",u=t.computed(e),c=u.subscribe(n,null,i),s=c.dispose;return c.dispose=function(){s.call(this),u.dispose()},o&&u.subscribe(function(){c.dispose()}),c}function d(e,t){return m(e,t)||e[t],g(e,t).get}var v=t.utils.extend,h=t.utils.objectForEach,y=Object.defineProperty.bind(Object),g=Object.getOwnPropertyDescriptor.bind(Object),m=Function.prototype.call.bind(Object.prototype.hasOwnProperty),j=Function.prototype.call.bind(Array.prototype.slice),k=["pop","push","reverse","shift","sort","splice","unshift"],A=["remove","removeAll","destroy","destroyAll","replace","subscribe"],O="undefined"!=typeof Symbol?Symbol("ko_decorators"):"__ko_decorators__";e.component=n,e.observable=r,e.computed=o,e.observableArray=c,e.extend=l,e.autobind=b,e.subscribe=p,e.unwrap=d,Object.defineProperty(e,"__esModule",{value:!0})});
//# sourceMappingURL=knockout-decorators.min.js.map
{
"name": "knockout-decorators",
"version": "0.7.1",
"version": "0.8.0",
"description": "Decorators for use Knockout JS in TypeScript and ESNext environments",

@@ -5,0 +5,0 @@ "main": "dist/knockout-decorators.js",

@@ -36,8 +36,7 @@ # Knockout Decorators

* [@observable](#knockout-decorators-observable)
* [@computed](#knockout-decorators-computed)
* [@observableArray](#knockout-decorators-observableArray)
* [@computed](#knockout-decorators-computed)
* [@reaction](#knockout-decorators-reaction)
* [@extend](#knockout-decorators-extend)
* [@subscribe](#knockout-decorators-subscribe)
* [@component](#knockout-decorators-component)
* [subscribe](#knockout-decorators-subscribe)
* [unwrap](#knockout-decorators-unwrap)

@@ -49,2 +48,4 @@

[Changes from v0.7.1](#knockout-decorators-changelog)
#### <a name="knockout-decorators-observable"></a> @observable

@@ -64,2 +65,23 @@ Property decorator that creates hidden `ko.observable` with ES6 getter and setter for it

#### <a name="knockout-decorators-computed"></a> @computed
Accessor decorator that wraps ES6 getter to hidden `ko.pureComputed`
Setter is not wrapped to hidden `ko.pureComputed` and stays unchanged
```js
class Person {
@observable firstName = "";
@observable lastName = "";
@computed
get fullName() { return this.firstName + " " + this.lastName; }
set fullName(value) { [this.firstName, this.lastName] = value.trim().split(/\s+/g); }
}
let person = new Person();
ko.pureComputed(() => person.fullName).subscribe(console.log.bind(console));
person.fullName = " John Smith " // [console] ➜ "John Smith"
```
<br>
#### <a name="knockout-decorators-observableArray"></a> @observableArray

@@ -96,59 +118,2 @@ Property decorator that creates hidden `ko.observableArray` with ES6 getter and setter for it

#### <a name="knockout-decorators-computed"></a> @computed
Accessor decorator that wraps ES6 getter and setter (if defined) to hidden `ko.pureComputed`
```js
class Person {
@observable firstName = "";
@observable lastName = "";
@computed
get fullName() { return this.firstName + " " + this.lastName; }
set fullName(value) { [this.firstName, this.lastName] = value.trim().split(/\s+/g); }
}
let person = new Person();
ko.pureComputed(() => person.fullName).subscribe(console.log.bind(console));
person.fullName = " John Smith " // [console] ➜ "John Smith"
```
<br>
#### <a name="knockout-decorators-reaction"></a> @reaction
Replace original method with factory that produces `ko.computed` from original method
```js
@reaction
@reaction(autoDispose: boolean)
```
| Argument | Default | Description |
|:------------|:--------|:-------------------------------------------------------------------------------|
| autoDispose | `true` | if true then computed will be disposed when entire decorated class is disposed |
Method that decorated with `@reaction` evaluates once when explicitely invoked (this call creates hidden `ko.computed`)
and every times when it's observable (or computed) dependencies are changed.
Hidden `ko.computed` will be disposed when entire decorated class is disposed (if we don't set `autoDispose` to `false`)
```js
class BlogPage {
@observable postId = 0;
@observable pageData: any;
constructor(blogId: ko.Observable<number>) {
const computed = this.onRoute(blogId);
// subscribe onRoute handler to changes
// then we can do whatever with created computed
}
// 'dispose()' method is redefined such that it disposes hidded 'onRoute' computed
// if original class already has 'dispose()' method then it would be wrapped by new method
@reaction async onRoute(blogId: ko.Observable<number>) {
const resp = await fetch(`/blog/${ blogId() }/post/${ this.postId }`);
this.pageData = await resp.json();
}
}
```
<br>
#### <a name="knockout-decorators-extend"></a> @extend

@@ -172,2 +137,7 @@ Apply extenders to decorated `@observable`

@observable second = "";
@extend({ rateLimit: 500 })
@computed get both() {
return this.first + " " + this.second;
}

@@ -182,52 +152,2 @@ getExtender() {

#### <a name="knockout-decorators-subscribe"></a> @subscribe
Subscribe to `@observable` by name or by specifying callback explicitely
```js
@subscribe(callback: (value: any) => void, event?: string, autoDispose?: boolean)
@subscribe(targetOrCallback: string | symbol, event?: string, autoDispose?: boolean)
```
| Argument | Default | Description |
|:-----------------|:--------|:-------------------------------------------------------------------------------|
| callback | | Subscription handler method |
| targetOrCallback | | Name of subscription handler method or name of `@observable` property |
| event | `null` | Knockout subscription event |
| autoDispose | `true` | if true then computed will be disposed when entire decorated class is disposed |
We can define name of handler when we decorate `@observable` or define name of `@observable` when decorate handler.
Subscriptions will be disposed when entire decorated class is disposed (if we don't set `autoDispose` to `false`)
```js
class ViewModel {
// specify callback
@subscribe("onFirstChanged")
@observable first = "";
onFirstChanged(value) {}
@observable second = "";
// specify observable
@subscribe("second")
onSecondChanged(value) {}
}
```
Also whe can pass subscription handler directly.
Then it will be invoked with ViewModel instance as `this` argument.
And we can specify subscription `event`
```js
class ViewModel {
operationLog = [];
@subscribe(ViewModel.prototype.onArrayChange, "arrayChange")
@observableArray array = [1, 2, 3]
onArrayChange(changes) {
this.operationLog.push(...changes);
}
}
```
<br>
#### <a name="knockout-decorators-component"></a> @component

@@ -300,4 +220,44 @@ Shorthand for registering Knockout component by decorating ViewModel class

#### <a name="knockout-decorators-subscribe"></a> subscribe
Subscribe to `@observable` or `@computed` dependency with creation of hidden `ko.computed()`
```js
subscribe<T>(getDependency: () => T, callback: (value: T) => void, options?: {
once?: boolean,
event?: string,
}): KnockoutSubscription
```
| Argument | Default | Description |
|:--------------|:-----------|:--------------------------------------------------------------------|
| getDependency | | Function for getting observeble property |
| callback | | Callback that handle dependency changes |
| options | `null` | Options object |
| options.once | `false` | If `true` then subscription will be disposed after first invocation |
| optons.event | `"change"` | Event for passing to Knockout native `subscribe()` |
```js
class ViewModel {
@observable field = "";
constructor() {
subscribe(() => this.field, (value) => {
console.log(value);
});
subscribe(() => this.field, (value) => {
console.log(value);
}, { once: true });
subscribe(() => this.field, (value) => {
console.log(value);
}, { event: "beforeChange" });
}
}
```
<br>
#### <a name="knockout-decorators-unwrap"></a> unwrap
Get internal `ko.observable()` for property decodated by `@observable`
or internal `ko.pureComputed()` for property decodated by `@computed`
```js

@@ -338,3 +298,2 @@ unwrap(instance: Object, key: string | symbol): any;

<br>

@@ -360,1 +319,39 @@

```
<br>
### <a name="knockout-decorators-changelog"></a>
### Breaking changes from v0.7.1 to 0.8.0
1. Removed `@subscribe` decorator
2. Removed `@reaction` decorator
3. Added `subscribe(() => this.observableProp, (value) => { ... })` function
4. Added `unwrap(this, "observablePropName")` function
Native `ko.computed` with side effects can be used in all places
where we use `@reaction` decorator.
In v0.7.1 and earlier `@subscribe` decorator can be used only with `@observable`
but not with `@computed`. To avoid this restriction we can create `ko.pureComputed`
and subscribe to it:
```js
class ViewModel {
@computed get computedProp() { ... }
constructor() {
ko.pureComputed(() => this.computedProp).subscribe((value) => { ... });
}
}
```
So in 0.8.0 instead of `@subscribe` decorator there is shorthand function `subscribe`
with some extra functionality like "subscribe once":
```js
class ViewModel {
@computed get computedProp() { ... }
constructor() {
subscribe(() => this.computedProp, (value) => { ... });
}
}
```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc