Skip to content

Commit

Permalink
Merge pull request #80 from dxinteractive/feature/derive-branches
Browse files Browse the repository at this point in the history
fix: make onderive value specific to branch it was called at
  • Loading branch information
dxinteractive authored Feb 27, 2022
2 parents e659671 + 5002d0d commit 739f902
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 7 deletions.
25 changes: 18 additions & 7 deletions packages/dendriform/src/Dendriform.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export type DeriveCallbackDetails<V> = InternalMetaDetails & {
};
export type DeriveCallback<V> = (newValue: V, details: DeriveCallbackDetails<V>) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type DeriveCallbackRef = [DeriveCallback<any>];
export type DeriveCallbackRef = [string, DeriveCallback<any>];

export type CancelCallback = (message: string) => void;

Expand Down Expand Up @@ -265,12 +265,20 @@ export class Core<C,P extends Plugins> {
return path;
};


getValue = (id: string): unknown => {
const path = this.getPath(id);
if(!path) return undefined;
return getIn(this.state.value, path);
};

getRevertValue = (id: string): unknown => {
const {stateRevert} = this;
const path = this.getPath(id);
if(!path || !stateRevert) return undefined;
return getIn(stateRevert.value, path);
};

getKey = (id: string): unknown => {
const path = this.getPath(id);
return path ? path.slice(-1)[0] : undefined;
Expand Down Expand Up @@ -490,24 +498,27 @@ export class Core<C,P extends Plugins> {
if(this.internalState.deriving) return;
this.internalState.deriving = true;

const [deriveCallback] = deriveCallbackRef;
const [id, deriveCallback] = deriveCallbackRef;
const patches = this.internalState.changeBuffer ?? new HistoryItem();

const nextValue = this.getValue(id);
const prevValue = this.getRevertValue(id);

const details = {
...internalMeta,
patches,
prev: {
value: this.stateRevert?.value,
value: prevValue,
nodes: this.stateRevert?.nodes
},
next: {
value: this.state.value,
value: nextValue,
nodes: this.state.nodes
},
id: '0'
id
};

deriveCallback(this.state.value, details);
deriveCallback(nextValue, details);
this.internalState.deriving = false;
};

Expand Down Expand Up @@ -836,7 +847,7 @@ export class Dendriform<V,P extends Plugins = undefined> {
};

onDerive(callback: DeriveCallback<V>): (() => void) {
const deriveCallback: DeriveCallbackRef = [callback];
const deriveCallback: DeriveCallbackRef = [this.id, callback];
this.core.deriveCallbackRefs.add(deriveCallback);

// call immediately, and dont add to history
Expand Down
29 changes: 29 additions & 0 deletions packages/dendriform/test/Dendriform.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,35 @@ describe(`Dendriform`, () => {

});

test(`should allow derivers on branched forms`, () => {

const form = new Dendriform({
name: 'boo',
letters: 0
});

const deriver = jest.fn();

form.branch('name').onDerive(deriver);
form.set(draft => {
draft.name = 'baa';
});

expect(deriver).toHaveBeenCalledTimes(2);
expect(deriver.mock.calls[1][0]).toBe('baa');
expect(deriver.mock.calls[1][1].id).toBe('1');
expect(deriver.mock.calls[1][1].prev.value).toBe('boo');
expect(deriver.mock.calls[1][1].next.value).toBe('baa');

// should always derive, for now, even if source field does not change

form.set(draft => {
draft.letters = 2;
});

expect(deriver).toHaveBeenCalledTimes(3);
});

test(`should handle multiple derivers on same form, calling them sequentially`, () => {

const form = new Dendriform({
Expand Down

0 comments on commit 739f902

Please sign in to comment.