mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Remove child/parent state concept in persistedStateProvider (#15737)
* Remove child/parent state concept in persistedStateProvider Looks like the only time it was used was when dashboard created child ui states for visualize and saved searches. We’re now all handling this state passing via the embeddable layer. * Remove more parent/child tests * Remove extra spot that referenced the two removed parameters
This commit is contained in:
parent
1968a1b1cf
commit
82901c8408
4 changed files with 24 additions and 443 deletions
|
@ -2,7 +2,6 @@ export function getContainerApiMock(config = {}) {
|
|||
const containerApiMockDefaults = {
|
||||
addFilter: () => {},
|
||||
getAppState: () => {},
|
||||
createChildUistate: () => {},
|
||||
registerPanelIndexPattern: () => {},
|
||||
updatePanel: () => {}
|
||||
};
|
||||
|
|
|
@ -44,17 +44,6 @@ describe('Persisted State Provider', function () {
|
|||
expect(persistedState.get()).to.not.equal(val);
|
||||
});
|
||||
|
||||
it('should not throw if creating valid child object', function () {
|
||||
const run = function () {
|
||||
const val = { red: 'blue' };
|
||||
const path = ['test.path'];
|
||||
const parent = new PersistedState();
|
||||
new PersistedState(val, path, parent);
|
||||
};
|
||||
|
||||
expect(run).not.to.throwException();
|
||||
});
|
||||
|
||||
it('should throw if given an invalid value', function () {
|
||||
const run = function () {
|
||||
const val = 'bananas';
|
||||
|
@ -65,287 +54,6 @@ describe('Persisted State Provider', function () {
|
|||
expect(err).to.be.a(PersistedStateError);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not throw if given primitive to child', function () {
|
||||
const run = function () {
|
||||
const val = 'bananas';
|
||||
const path = ['test.path'];
|
||||
const parent = new PersistedState();
|
||||
new PersistedState(val, path, parent);
|
||||
};
|
||||
|
||||
expect(run).not.to.throwException();
|
||||
});
|
||||
|
||||
it('should throw if given an invalid parent object', function () {
|
||||
const run = function () {
|
||||
const val = { red: 'blue' };
|
||||
const path = ['test.path'];
|
||||
const parent = {};
|
||||
new PersistedState(val, path, parent);
|
||||
};
|
||||
|
||||
expect(run).to.throwException(function (err) {
|
||||
expect(err).to.be.a(PersistedStateError);
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw if given a parent without a path', function () {
|
||||
const run = function () {
|
||||
const val = { red: 'blue' };
|
||||
let path;
|
||||
const parent = new PersistedState();
|
||||
|
||||
new PersistedState(val, path, parent);
|
||||
};
|
||||
|
||||
expect(run).to.throwException(function (err) {
|
||||
expect(err).to.be.a(PersistedStateError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('child state creation', function () {
|
||||
let childState;
|
||||
|
||||
it('should not append the child state to the parent, without parent value', function () {
|
||||
const childIndex = 'i can haz child';
|
||||
const persistedState = new PersistedState();
|
||||
childState = persistedState.createChild(childIndex);
|
||||
|
||||
// parent state should not contain the child state
|
||||
expect(persistedState.get()).to.not.have.property(childIndex);
|
||||
expect(persistedState.get()).to.eql({});
|
||||
});
|
||||
|
||||
it('should not append the child state to the parent, with parent value', function () {
|
||||
const childIndex = 'i can haz child';
|
||||
const persistedStateValue = { original: true };
|
||||
const persistedState = new PersistedState(persistedStateValue);
|
||||
childState = persistedState.createChild(childIndex);
|
||||
|
||||
// child state should be empty, we didn't give it any default data
|
||||
expect(childState.get()).to.be(undefined);
|
||||
|
||||
// parent state should not contain the child state
|
||||
expect(persistedState.get()).to.not.have.property(childIndex);
|
||||
expect(persistedState.get()).to.eql(persistedStateValue);
|
||||
});
|
||||
|
||||
it('should append the child state to the parent, with parent and child values', function () {
|
||||
const childIndex = 'i can haz child';
|
||||
const childStateValue = { tacos: 'yes please' };
|
||||
const persistedStateValue = { original: true };
|
||||
const persistedState = new PersistedState(persistedStateValue);
|
||||
childState = persistedState.createChild(childIndex, childStateValue);
|
||||
|
||||
// parent state should contain the child and its original state value
|
||||
const parentState = persistedState.get();
|
||||
expect(parentState).to.have.property('original', true);
|
||||
expect(parentState).to.have.property(childIndex);
|
||||
expect(parentState[childIndex]).to.eql(childStateValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deep child state creation', function () {
|
||||
it('should delegate get/set calls to parent state', function () {
|
||||
const children = [{
|
||||
path: 'first*child',
|
||||
value: { first: true, second: false }
|
||||
}, {
|
||||
path: 'second child',
|
||||
value: { first: false, second: true }
|
||||
}];
|
||||
const persistedStateValue = { original: true };
|
||||
const persistedState = new PersistedState(persistedStateValue);
|
||||
|
||||
// first child is a child of the parent persistedState
|
||||
children[0].instance = persistedState.createChild(children[0].path, children[0].value);
|
||||
// second child is a child of the first child
|
||||
children[1].instance = children[0].instance.createChild(children[1].path, children[1].value);
|
||||
|
||||
// second child getter should only return second child value
|
||||
expect(children[1].instance.get()).to.eql(children[1].value);
|
||||
|
||||
// parent should contain original props and first child path, but not the second child path
|
||||
const parentState = persistedState.get();
|
||||
_.keys(persistedStateValue).forEach(function (key) {
|
||||
expect(parentState).to.have.property(key);
|
||||
});
|
||||
expect(parentState).to.have.property(children[0].path);
|
||||
expect(parentState).to.not.have.property(children[1].path);
|
||||
|
||||
// second child path should be inside the first child
|
||||
const firstChildState = children[0].instance.get();
|
||||
expect(firstChildState).to.have.property(children[1].path);
|
||||
expect(firstChildState[children[1].path]).to.eql(children[1].value);
|
||||
|
||||
// check that the second child is still accessible from the parent instance
|
||||
const firstChild = persistedState.get(children[0].path);
|
||||
expect(firstChild).to.have.property(children[1].path);
|
||||
});
|
||||
});
|
||||
|
||||
describe('child state removal', function () {
|
||||
it('should clear path from parent state', function () {
|
||||
const persistedState = new PersistedState();
|
||||
persistedState.createChild('child', { userId: 1234 });
|
||||
expect(persistedState.get()).to.eql({ child: { userId: 1234 } });
|
||||
persistedState.removeChild('child');
|
||||
expect(persistedState.get()).to.eql({});
|
||||
});
|
||||
|
||||
it('should reset original parent value at path', function () {
|
||||
const persistedState = new PersistedState({ user: 1234 });
|
||||
persistedState.createChild('user', { id: 5678 });
|
||||
expect(persistedState.get()).to.eql({ user: { id: 5678 } });
|
||||
|
||||
persistedState.removeChild('user');
|
||||
expect(persistedState.get()).to.eql({ user: 1234 });
|
||||
});
|
||||
|
||||
it('should clear changedState', function () {
|
||||
const persistedState = new PersistedState({ user: 1234 });
|
||||
const childState = persistedState.createChild('user');
|
||||
childState.set('name', 'user name');
|
||||
expect(persistedState.getChanges()).to.eql({ user: { name: 'user name' } });
|
||||
|
||||
persistedState.removeChild('user');
|
||||
expect(persistedState.getChanges()).to.eql({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('deep child state removal', function () {
|
||||
it('should clear path from parent state', function () {
|
||||
const persistedState = new PersistedState();
|
||||
persistedState.createChild('child.state', { userId: 1234 });
|
||||
expect(persistedState.get()).to.eql({ child: { state: { userId: 1234 } } });
|
||||
persistedState.removeChild('child.state');
|
||||
expect(persistedState.get()).to.eql({});
|
||||
});
|
||||
|
||||
it('should reset original parent value at path', function () {
|
||||
const persistedState = new PersistedState({ user: { id: 1234 } });
|
||||
persistedState.createChild('user.id', 5678);
|
||||
expect(persistedState.get()).to.eql({ user: { id: 5678 } });
|
||||
|
||||
persistedState.removeChild('user.id');
|
||||
expect(persistedState.get()).to.eql({ user: { id: 1234 } });
|
||||
});
|
||||
|
||||
it('should reset original parent other values at path', function () {
|
||||
const persistedState = new PersistedState({ user: { name: 'user' } });
|
||||
persistedState.createChild('user.id', 5678);
|
||||
expect(persistedState.get()).to.eql({ user: { name: 'user', id: 5678 } });
|
||||
|
||||
persistedState.removeChild('user.id');
|
||||
expect(persistedState.get()).to.eql({ user: { name: 'user' } });
|
||||
});
|
||||
|
||||
it('should clear the changed state', function () {
|
||||
const persistedState = new PersistedState({ user: { id: 1234 } });
|
||||
const childState = persistedState.createChild('user.name');
|
||||
childState.set('user name');
|
||||
expect(persistedState.getChanges()).to.eql({ user: { name: 'user name' } });
|
||||
|
||||
persistedState.removeChild('user.name');
|
||||
expect(persistedState.getChanges()).to.eql({});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('child state conditions', function () {
|
||||
it('should be merged with the parent state', function () {
|
||||
const parent = new PersistedState({ name: 'test' });
|
||||
parent.createChild('child', 'value');
|
||||
expect(parent.get()).to.eql({
|
||||
name: 'test',
|
||||
child: 'value'
|
||||
});
|
||||
|
||||
parent.set('id', 1234);
|
||||
expect(parent.get()).to.eql({
|
||||
id: 1234,
|
||||
name: 'test',
|
||||
child: 'value'
|
||||
});
|
||||
|
||||
parent.set({});
|
||||
expect(parent.get()).to.eql({
|
||||
child: 'value'
|
||||
});
|
||||
});
|
||||
|
||||
it('should give child state precedence', function () {
|
||||
const parent = new PersistedState({ user: { id: 1234, name: 'test' } });
|
||||
parent.createChild('user', { name: 'child test' });
|
||||
expect(parent.get()).to.eql({
|
||||
user: {
|
||||
id: 1234,
|
||||
name: 'child test'
|
||||
}
|
||||
});
|
||||
|
||||
parent.set({});
|
||||
expect(parent.get()).to.eql({ user: { name: 'child test' } });
|
||||
});
|
||||
|
||||
it('should be cleaned up with removeChild', function () {
|
||||
const parent = new PersistedState({ name: 'test' });
|
||||
parent.createChild('child', 'value');
|
||||
expect(parent.get()).to.eql({
|
||||
name: 'test',
|
||||
child: 'value'
|
||||
});
|
||||
|
||||
parent.removeChild('child');
|
||||
expect(parent.get()).to.eql({
|
||||
name: 'test'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('colliding child paths and parent state values', function () {
|
||||
it('should not change the child path value by default', function () {
|
||||
const childIndex = 'childTest';
|
||||
const persistedStateValue = {};
|
||||
persistedStateValue[childIndex] = { overlapping_index: true };
|
||||
|
||||
const persistedState = new PersistedState(persistedStateValue);
|
||||
let state = persistedState.get();
|
||||
expect(state).to.have.property(childIndex);
|
||||
expect(state[childIndex]).to.eql(persistedStateValue[childIndex]);
|
||||
|
||||
const childState = persistedState.createChild(childIndex);
|
||||
expect(childState.get()).to.eql(persistedStateValue[childIndex]);
|
||||
|
||||
// make sure the parent state is still the same
|
||||
state = persistedState.get();
|
||||
expect(state).to.have.property(childIndex);
|
||||
expect(state[childIndex]).to.eql(persistedStateValue[childIndex]);
|
||||
});
|
||||
|
||||
it('should merge default child state', function () {
|
||||
const childIndex = 'childTest';
|
||||
const childStateValue = { child_index: false };
|
||||
const persistedStateValue = {};
|
||||
persistedStateValue[childIndex] = { parent_index: true };
|
||||
|
||||
const persistedState = new PersistedState(persistedStateValue);
|
||||
let state = persistedState.get();
|
||||
expect(state).to.have.property(childIndex);
|
||||
expect(state[childIndex]).to.eql(persistedStateValue[childIndex]);
|
||||
|
||||
// pass in child state value
|
||||
const childState = persistedState.createChild(childIndex, childStateValue);
|
||||
|
||||
// parent's default state is merged with child state
|
||||
const compare = _.merge({}, childStateValue, persistedStateValue[childIndex]);
|
||||
expect(childState.get()).to.eql(compare);
|
||||
state = persistedState.get();
|
||||
expect(state).to.have.property(childIndex);
|
||||
expect(state[childIndex]).to.eql(compare);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mutation', function () {
|
||||
|
@ -376,27 +84,6 @@ describe('Persisted State Provider', function () {
|
|||
const json = persistedState.toJSON();
|
||||
expect(json).to.eql(persistedStateValue);
|
||||
});
|
||||
|
||||
it('should return the JSON representation of the child state', function () {
|
||||
const persistedState = new PersistedState(persistedStateValue);
|
||||
const childState = persistedState.createChild('awesome', { pants: false });
|
||||
|
||||
expect(childState.toJSON()).to.eql({ pants: false });
|
||||
// verify JSON output of the parent state
|
||||
const parentCompare = _.assign({ awesome: { pants: false } }, persistedStateValue);
|
||||
expect(persistedState.toJSON()).to.eql(parentCompare);
|
||||
});
|
||||
|
||||
it('should export stringified version of state', function () {
|
||||
const persistedState = new PersistedState(persistedStateValue);
|
||||
const childState = persistedState.createChild('awesome', { pants: false });
|
||||
|
||||
const data = childState.toString();
|
||||
expect(JSON.parse(data)).to.eql({ pants: false });
|
||||
// verify JSON output of the parent state
|
||||
const parentCompare = _.assign({ awesome: { pants: false } }, persistedStateValue);
|
||||
expect(JSON.parse(persistedState.toString())).to.eql(parentCompare);
|
||||
});
|
||||
});
|
||||
|
||||
describe('importing state from JSON string (hydration)', function () {
|
||||
|
@ -449,15 +136,6 @@ describe('Persisted State Provider', function () {
|
|||
expect(persistedState.get('hello')).to.eql({ nouns: ['world', 'humans', 'everyone'] });
|
||||
expect(persistedState.get('hello.nouns')).to.eql(['world', 'humans', 'everyone']);
|
||||
});
|
||||
|
||||
it('should pass defaults to parent delegation', function () {
|
||||
const persistedState = new PersistedState({ parent: true });
|
||||
const childState = persistedState.createChild('child', { account: { name: 'first child' } });
|
||||
const defaultValue = 'i have no data';
|
||||
|
||||
expect(childState.get('account.name', defaultValue)).to.eql('first child');
|
||||
expect(childState.get('account.age', defaultValue)).to.eql(defaultValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('set state', function () {
|
||||
|
@ -625,51 +303,5 @@ describe('Persisted State Provider', function () {
|
|||
persistedState.set('checker.events', 'i changed');
|
||||
expect(getByType('change')).to.have.length(1);
|
||||
});
|
||||
|
||||
it('should not emit change when createChild has no value', function () {
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
persistedState.createChild('checker');
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
});
|
||||
|
||||
it('should not emit change when createChild is same value', function () {
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
persistedState.createChild('checker', { events: 'event tests' });
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
persistedState.createChild('checker.events', 'event tests');
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
});
|
||||
|
||||
it('should emit change when createChild changes existing value', function () {
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
persistedState.createChild('checker', { events: 'changed via child' });
|
||||
expect(getByType('change')).to.have.length(1);
|
||||
});
|
||||
|
||||
it('should not emit when createChild set to silent', function () {
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
persistedState.createChild('checker', { events: 'changed via child' }, true);
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
});
|
||||
|
||||
it('should emit change when createChild adds new value', function () {
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
persistedState.createChild('new.path', { another: 'thing' });
|
||||
expect(getByType('change')).to.have.length(1);
|
||||
});
|
||||
|
||||
it('should emit on parent and child instances', function (done) {
|
||||
const child = persistedState.createChild('checker');
|
||||
expect(getByType('change')).to.have.length(0);
|
||||
|
||||
// parent and child should emit, set up listener to test
|
||||
child.on('change', function () {
|
||||
// child fired, make sure parent fires as well
|
||||
expect(getByType('change')).to.have.length(1);
|
||||
done();
|
||||
});
|
||||
|
||||
child.set('events', 'changed via child set');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -25,8 +25,8 @@ module.factory('PersistedState', ($injector) => {
|
|||
// Extend PersistedState to override the EmitterClass class with
|
||||
// our Angular friendly version.
|
||||
return class AngularPersistedState extends PersistedState {
|
||||
constructor(value, path, parent, silent) {
|
||||
super(value, path, parent, silent, Events);
|
||||
constructor(value, path) {
|
||||
super(value, path, Events);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -30,43 +30,32 @@ export class PersistedState {
|
|||
*
|
||||
* @param value
|
||||
* @param path
|
||||
* @param parent
|
||||
* @param silent
|
||||
* @param EmitterClass {SimpleEmitter} - a SimpleEmitter class that this class will extend. Can be used to
|
||||
* inherit a custom event emitter. For example, the EventEmitter is an "angular-ized" version
|
||||
* for angular components which automatically triggers a digest loop for every registered
|
||||
* handler. TODO: Get rid of the need for EventEmitter by wrapping handlers that require it
|
||||
* in a special function that will handler triggering the digest loop.
|
||||
* handler. TODO: replace angularized SimpleEmitter and force angular callers to handle digest loops manually ala
|
||||
* https://github.com/elastic/kibana/issues/13855
|
||||
*/
|
||||
constructor(value, path, parent, silent, EmitterClass = SimpleEmitter) {
|
||||
constructor(value, path, EmitterClass = SimpleEmitter) {
|
||||
EmitterClass.call(this);
|
||||
|
||||
this._EmitterClass = EmitterClass;
|
||||
this._path = this._setPath(path);
|
||||
this._parent = parent || false;
|
||||
|
||||
_.forOwn(EmitterClass.prototype, (method, methodName) => {
|
||||
this[methodName] = function () {
|
||||
return EmitterClass.prototype[methodName].apply(this._parent || this, arguments);
|
||||
return EmitterClass.prototype[methodName].apply(this, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
// Some validations
|
||||
if (this._parent) {
|
||||
if (this._path.length <= 0) {
|
||||
throw new PersistedStateError('PersistedState child objects must contain a path');
|
||||
}
|
||||
if (!(this._parent instanceof PersistedState)) {
|
||||
throw new PersistedStateError('Parent object must be an instance of PersistedState');
|
||||
}
|
||||
} else if (!this._path.length && value && !_.isPlainObject(value)) {
|
||||
if (!this._path.length && value && !_.isPlainObject(value)) {
|
||||
throw new PersistedStateError('State value must be a plain object');
|
||||
}
|
||||
|
||||
value = value || this._getDefault();
|
||||
|
||||
// copy passed state values and create internal trackers
|
||||
(silent) ? this.setSilent(value) : this.set(value);
|
||||
this.set(value);
|
||||
this._initialized = true; // used to track state changes
|
||||
}
|
||||
|
||||
|
@ -103,35 +92,12 @@ export class PersistedState {
|
|||
_.set(this._mergedState, keyPath, origValue);
|
||||
}
|
||||
|
||||
// clean up the changedState and defaultChildState trees
|
||||
// clean up the changedState tree
|
||||
this._cleanPath(path, this._changedState);
|
||||
this._cleanPath(path, this._defaultChildState);
|
||||
|
||||
if (!_.isEqual(currentValue, origValue)) this.emit('change');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path {String}
|
||||
* @param value {Object} The uiState to store.
|
||||
* @param silent {Boolean}
|
||||
* @returns {PersistedState}
|
||||
*/
|
||||
createChild(path, value, silent) {
|
||||
this._setChild(this._getIndex(path), value, this._parent || this);
|
||||
return new PersistedState(value, this._getIndex(path), this._parent || this, silent, this._EmitterClass);
|
||||
}
|
||||
|
||||
removeChild(path) {
|
||||
const origValue = _.get(this._defaultState, this._getIndex(path));
|
||||
|
||||
if (_.isUndefined(origValue)) {
|
||||
this.reset(path);
|
||||
} else {
|
||||
this.set(path, origValue);
|
||||
}
|
||||
}
|
||||
|
||||
getChanges() {
|
||||
return _.cloneDeep(this._changedState);
|
||||
}
|
||||
|
@ -177,8 +143,7 @@ export class PersistedState {
|
|||
}
|
||||
|
||||
_getDefault() {
|
||||
const def = (this._hasPath()) ? undefined : {};
|
||||
return (this._parent ? this.get() : def);
|
||||
return this._hasPath() ? undefined : {};
|
||||
}
|
||||
|
||||
_setPath(path) {
|
||||
|
@ -189,19 +154,11 @@ export class PersistedState {
|
|||
return (isString) ? [this._getIndex(path)] : path;
|
||||
}
|
||||
|
||||
_setChild(path, value, parent) {
|
||||
parent._defaultChildState = parent._defaultChildState || {};
|
||||
_.set(parent._defaultChildState, path, value);
|
||||
}
|
||||
|
||||
_hasPath() {
|
||||
return this._path.length > 0;
|
||||
}
|
||||
|
||||
_get(key, def) {
|
||||
// delegate to parent instance
|
||||
if (this._parent) return this._parent._get(this._getIndex(key), def);
|
||||
|
||||
// no path and no key, get the whole state
|
||||
if (!this._hasPath() && _.isUndefined(key)) {
|
||||
return this._mergedState;
|
||||
|
@ -210,7 +167,7 @@ export class PersistedState {
|
|||
return _.get(this._mergedState, this._getIndex(key), def);
|
||||
}
|
||||
|
||||
_set(key, value, silent, initialChildState) {
|
||||
_set(key, value, silent) {
|
||||
const self = this;
|
||||
let stateChanged = false;
|
||||
const initialState = !this._initialized;
|
||||
|
@ -224,47 +181,40 @@ export class PersistedState {
|
|||
else this._defaultState = _.set({}, keyPath, value);
|
||||
}
|
||||
|
||||
// delegate to parent instance, passing child's default value
|
||||
if (this._parent) {
|
||||
return this._parent._set(keyPath, value, silent, initialState);
|
||||
}
|
||||
|
||||
// everything in here affects only the parent state
|
||||
if (!initialState) {
|
||||
// no path and no key, set the whole state
|
||||
if (!this._hasPath() && _.isUndefined(key)) {
|
||||
// compare changedState and new state, emit an event when different
|
||||
stateChanged = !_.isEqual(this._changedState, value);
|
||||
if (!initialChildState) {
|
||||
this._changedState = value;
|
||||
this._mergedState = _.cloneDeep(value);
|
||||
}
|
||||
this._changedState = value;
|
||||
this._mergedState = _.cloneDeep(value);
|
||||
} else {
|
||||
// check for changes at path, emit an event when different
|
||||
const curVal = hasKeyPath ? this.get(keyPath) : this._mergedState;
|
||||
stateChanged = !_.isEqual(curVal, value);
|
||||
|
||||
if (!initialChildState) {
|
||||
// arrays are merge by index, not desired - ensure they are replaced
|
||||
if (Array.isArray(_.get(this._mergedState, keyPath))) {
|
||||
if (hasKeyPath) _.set(this._mergedState, keyPath, undefined);
|
||||
else this._mergedState = undefined;
|
||||
}
|
||||
// arrays are merge by index, not desired - ensure they are replaced
|
||||
if (Array.isArray(_.get(this._mergedState, keyPath))) {
|
||||
if (hasKeyPath) _.set(this._mergedState, keyPath, undefined);
|
||||
else this._mergedState = undefined;
|
||||
}
|
||||
|
||||
if (hasKeyPath) _.set(this._changedState, keyPath, value);
|
||||
else this._changedState = _.isPlainObject(value) ? value : {};
|
||||
if (hasKeyPath) {
|
||||
_.set(this._changedState, keyPath, value);
|
||||
} else {
|
||||
this._changedState = _.isPlainObject(value) ? value : {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update the merged state value
|
||||
const targetObj = this._mergedState || _.cloneDeep(this._defaultState);
|
||||
const sourceObj = _.merge({}, this._defaultChildState, this._changedState);
|
||||
const sourceObj = _.merge({}, this._changedState);
|
||||
|
||||
// handler arguments are (targetValue, sourceValue, key, target, source)
|
||||
const mergeMethod = function (targetValue, sourceValue, mergeKey) {
|
||||
// if not initial state, skip default merge method (ie. return value, see note below)
|
||||
if (!initialState && !initialChildState && _.isEqual(keyPath, self._getIndex(mergeKey))) {
|
||||
if (!initialState && _.isEqual(keyPath, self._getIndex(mergeKey))) {
|
||||
// use the sourceValue or fall back to targetValue
|
||||
return !_.isUndefined(sourceValue) ? sourceValue : targetValue;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue