diff --git a/examples/example.js b/examples/example.js index ce391b4..70fd6e7 100644 --- a/examples/example.js +++ b/examples/example.js @@ -10,7 +10,8 @@ class Example extends RxClass { const example = new Example({ _rx_ : { - // handler: value => {console.log('-----------default subscription handler-------', value)} + handler: value => {console.log('-----------default subscription handler-------', value)}, + amendValue: val => val + 3 } }) @@ -21,16 +22,26 @@ console.log('--------------------------') example.on('changed', (prop) => console.log('emitted----a property changed-----',prop)) example.on('test', (val) => console.log('emitted value of test',val)) -console.log('making \'test\' reactive') +console.log('making \'test\' reactive with default amend of add 3') example.rxAdd('test') console.log('changing test to 20, 30 directly') example.test = 20 +example.rxAmendValue() // removes global amend example.test = 30 example.rxSubscribe('test','custom',(prop)=>console.log('#############late subscription to \'test\' after 30 ############',prop)) +console.log('amending emitted value with path',example.rxAmendValue('test','path')) console.log('changing test to 40 via set') example.set('test',40) +console.log( + 'amending emitted value custom function', + example.rxAmendValue('test',val => { return { value:val+5, msg:'additional 5 was added to set value'}}) +) +example.set('test',50) +console.log('removing amend function ',example.rxAmendValue('test',null)) +example.set('test',60) console.log('making a deeper property \'another.foo\' reactive') +console.log('changing any default amend function ',example.rxAmendValue(val=> val + ':amended')) example.rxAdd('another.foo') example.another.foo = 7 diff --git a/package.json b/package.json index 52f3b93..da2005b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@uci-utils/rx-class", - "version": "0.1.1", + "version": "0.1.2", "description": "class that support reactive properites", "main": "src/rx-class.js", "scripts": { @@ -23,12 +23,12 @@ }, "homepage": "https://github.com/uCOMmandIt/uci-utils#readme", "dependencies": { + "@uci-utils/set-value": "^3.0.3", "deep-equal": "^2.0.3", "get-value": "^3.0.1", "is-plain-obj": "^2.1.0", "is-plain-object": "^3.0.0", "rxjs": "^6.5.5", - "set-value": "^3.0.2", "traverse": "^0.6.6", "unset-value": "^1.0.0" }, diff --git a/src/rx-class.js b/src/rx-class.js index cf47813..5dc43a0 100644 --- a/src/rx-class.js +++ b/src/rx-class.js @@ -18,9 +18,11 @@ export default class RxClass extends EventEmitter { event: rxopts.event || 'changed', handler: rxopts.handler, props: {}, - hooks: [], + amendValue: rxopts.amendValue, + emit_path : rxopts.emit_path, + hooks: [], // will add to all setters root: '', // root path/namespace to added to all get/set paths - operators:[], + operators:[], // will add to all pipes skip: rxopts.skip == null ? 0 : rxopts.skip } } @@ -71,7 +73,9 @@ export default class RxClass extends EventEmitter { // console.log('moving',opts.value != null ? opts.value : value,path) rx.value = opts.value != null ? opts.value : value rx.path = path - rx.obs = from(new BehaviorSubject({value:rx.value, path:rx.path}).pipe( + rx.amendValue = opts.amendValue || this._rx_.amendValue || ((val) => val) + if (opts.emit_path || this._rx_.emit_path) rx.amendValue = (value,path) => {return {value:value, path: path}} + rx.obs = from(new BehaviorSubject(rx.amendValue(rx.value,rx.path)).pipe( // rx.obs = from(new ReplaySubject(1).pipe( skip(this._rx_.skip), distinctUntilChanged() @@ -80,6 +84,7 @@ export default class RxClass extends EventEmitter { )) // console.log(path,'---------------\n',Object.getOwnPropertyNames(Object.getPrototypeOf(rx.obs)),rx.obs.subscribe) rx.subs = {} + rx.hooks = [] this.rxSubscribe(rx,'_default',this._rx_.handler,) this.rxSubscribe(rx,(opts.subscribe || {}).name,(opts.subscribe ||{}).handler) const self = this @@ -92,10 +97,13 @@ export default class RxClass extends EventEmitter { set (value) { // console.log('in setter', path,value) rx.value = value - rx.obs.next({value:value, path:path}) - self.emit(opts.event || self._rx_.event,{value:value, path:path}) + value = rx.amendValue(value,path) + rx.obs.next(value) + self.emit(opts.event || self._rx_.event,value) self.emit(path,value) - self._rx_.hooks.forEach(hook=>hook.call(self,{value:value, path:path})) + // any hook function that already bound will use that context + self._rx_.hooks.forEach(hook=>hook.call(self,value)) + rx.hooks.forEach(hook=>hook.call(self,value)) } }) return true @@ -106,6 +114,18 @@ export default class RxClass extends EventEmitter { this._rx_.hooks[name]=func } + rxAmendValue(path,func) { + let rx = {} + if (arguments.length === 0 ) {this._rx_.amendValue= null;return} + if (typeof path === 'function') {this._rx_.amendValue=path;return} + rx = (typeof path === 'string') ? this._rxGetObj(path) : path + if (!rx) return false + func = func ? func : (val => val ) + console.log('amend', func) + rx.amendValue = func === 'path' ? (value,path) => {return {value:value, path: path}} : func + return !!rx.amendValue + } + // if name is only passed remove rxOperator(func,name) { this._rx_.operators[name]=func