Ignite properties now patch lists to capture push/pop events so that when used in a list template the whole list doesn't have to be rerendered. Also cleaned up some code and moved things around.

This commit is contained in:
2020-08-22 16:15:45 -07:00
parent a22d5cc6aa
commit 56530fc966
4 changed files with 154 additions and 27 deletions

View File

@ -3,9 +3,14 @@
* can be used to invoke call back functions when the value of the property changes.
*/
class IgniteProperty {
constructor() {
this.callbacks = [];
this._value = null;
constructor(val) {
this.onChangeCallbacks = [];
this.onPushCallbacks = [];
this.onPopCallbacks = [];
this._value = val;
//Attempt to patch the value if it's a list.
this.patchListValue();
}
get value() {
@ -16,15 +21,64 @@ class IgniteProperty {
var old = this._value;
this._value = val;
//Attempt to patch the value if it's a list.
this.patchListValue();
//Invoke any callbacks letting them know the value changed.
for (var i = 0; i < this.callbacks.length; i++) {
this.callbacks[i].invoke(old, val);
this.invokeOnChange(old, val);
}
patchListValue() {
if (Array.isArray(this._value)) {
let prop = this;
this._value.push = function () {
var len = Array.prototype.push.apply(this, arguments);
prop.invokeOnPush();
return len;
};
this._value.pop = function () {
var len = Array.prototype.pop.apply(this, arguments);
prop.invokeOnPop();
return len;
}
}
}
attach(onChange) {
var callback = new IgnitePropertyCallback(this, onChange);
this.callbacks.push(callback);
invokeOnChange(oldValue, newValue) {
for (var i = 0; i < this.onChangeCallbacks.length; i++) {
this.onChangeCallbacks[i].invoke(oldValue, newValue);
}
}
invokeOnPush() {
for (var i = 0; i < this.onPushCallbacks.length; i++) {
this.onPushCallbacks[i].invoke(null, this._value);
}
}
invokeOnPop() {
for (var i = 0; i < this.onPopCallbacks.length; i++) {
this.onPopCallbacks[i].invoke(null, this._value);
}
}
attachOnChange(onChange) {
var callback = new IgnitePropertyOnChangeCallback(this, onChange);
this.onChangeCallbacks.push(callback);
return callback;
}
attachOnPush(onPush) {
var callback = new IgnitePropertyOnPushCallback(this, onPush);
this.onPushCallbacks.push(callback);
return callback;
}
attachOnPop(onPop) {
var callback = new IgnitePropertyOnPopCallback(this, onPop);
this.onPopCallbacks.push(callback);
return callback;
}
}
@ -38,10 +92,10 @@ IgniteProperty.prototype.toString = function () {
}
/**
* The outline of a ignite property callback that allows
* The outline of a ignite property onchange callback that allows
* disconnecting of callbacks on demand when they are no longer needed.
*/
class IgnitePropertyCallback {
class IgnitePropertyOnChangeCallback {
constructor(property, callback) {
this.callback = callback;
this.property = property;
@ -57,7 +111,59 @@ class IgnitePropertyCallback {
this.callback = null;
if (this.property) {
this.property.callbacks = this.property.callbacks.filter(callback => callback != this);
this.property.onChangeCallbacks = this.property.onChangeCallbacks.filter(callback => callback != this);
this.property = null;
}
}
}
/**
* The outline of a ignite property onpush callback that allows
* disconnecting of callbacks on demand when they are no longer needed.
*/
class IgnitePropertyOnPushCallback {
constructor(property, callback) {
this.callback = callback;
this.property = property;
}
invoke(oldValue, newValue) {
if (this.callback) {
this.callback(oldValue, newValue);
}
}
disconnect() {
this.callback = null;
if (this.property) {
this.property.onPushCallbacks = this.property.onPushCallbacks.filter(callback => callback != this);
this.property = null;
}
}
}
/**
* The outline of a ignite property onpop callback that allows
* disconnecting of callbacks on demand when they are no longer needed.
*/
class IgnitePropertyOnPopCallback {
constructor(property, callback) {
this.callback = callback;
this.property = property;
}
invoke(oldValue, newValue) {
if (this.callback) {
this.callback(oldValue, newValue);
}
}
disconnect() {
this.callback = null;
if (this.property) {
this.property.onPopCallbacks = this.property.onPopCallbacks.filter(callback => callback != this);
this.property = null;
}
}