Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### 2.23.0

- `Improvement` — The `onChange` callback now accepts two arguments: EditorJS API and the CustomEvent with `type` and `detail` allowing to determine what happened with a Block
- `New` *Block API* — The new `dispatchChange()` method allows to manually trigger the 'onChange' callback. Useful when Tool made a state mutation that is invisible for editor core.

### 2.22.3

Expand Down
2 changes: 2 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ API for certain Block methods and properties. You can access it through `editor.

`validate(data: BlockToolData): Promise<boolean>` — calls Tool's validate method if exists

`dispatchChange(): void` - Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback. Can be useful for block changes invisible for editor core.

## Api object description

Common API interface.
Expand Down
8 changes: 8 additions & 0 deletions src/components/block/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ function BlockAPI(
validate(data: BlockToolData): Promise<boolean> {
return block.validate(data);
},

/**
* Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback
* Can be useful for block changes invisible for editor core.
*/
dispatchChange(): void {
block.dispatchChange();
},
};

Object.setPrototypeOf(this, blockAPI);
Expand Down
10 changes: 9 additions & 1 deletion src/components/block/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export default class Block extends EventsDispatcher<BlockEvents> {
/**
* Is fired when DOM mutation has been happened
*/
private didMutated = _.debounce((mutations: MutationRecord[]): void => {
private didMutated = _.debounce((mutations: MutationRecord[] = []): void => {
const shouldFireUpdate = !mutations.some(({ addedNodes = [], removedNodes }) => {
return [...Array.from(addedNodes), ...Array.from(removedNodes)]
.some(node => $.isElement(node) && (node as HTMLElement).dataset.mutationFree === 'true');
Expand Down Expand Up @@ -702,6 +702,14 @@ export default class Block extends EventsDispatcher<BlockEvents> {
this.removeInputEvents();
}

/**
* Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback
* Can be useful for block changes invisible for editor core.
*/
public dispatchChange(): void{
this.didMutated();
}

/**
* Call Tool instance destroy method
*/
Expand Down
63 changes: 63 additions & 0 deletions test/cypress/tests/api/block.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { BlockMutationType } from '../../../../types/events/block/mutation-type';

/**
* There will be described test cases of BlockAPI
*/
describe('BlockAPI', () => {
const firstBlock = {
id: 'bwnFX5LoX7',
type: 'paragraph',
data: {
text: 'The first block content mock.',
},
};
const editorDataMock = {
blocks: [
firstBlock,
],
};

/**
* EditorJS API is passed as the first parameter of the onChange callback
*/
const EditorJSApiMock = Cypress.sinon.match.any;

beforeEach(() => {
if (this && this.editorInstance) {
this.editorInstance.destroy();
} else {
const config = {
data: editorDataMock,
onChange: (): void => { console.log('something changed'); },
};

cy.createEditor(config).as('editorInstance');

cy.spy(config, 'onChange').as('onChange');
}
});

/**
* block.dispatchChange();
*/
describe('.dispatchChange()', () => {
/**
* Check that blocks.dispatchChange() triggers Editor 'onChange' callback
*/
it('should trigger onChange with corresponded block', () => {
cy.get('@editorInstance').then(async (editor: any) => {
const block = editor.blocks.getById(firstBlock.id);

block.dispatchChange();

cy.get('@onChange').should('be.calledWithMatch', EditorJSApiMock, Cypress.sinon.match({
type: BlockMutationType.Changed,
detail: {
index: 0,
},
}));
});
});
});

});
6 changes: 6 additions & 0 deletions types/api/block.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,10 @@ export interface BlockAPI {
* @return {Promise<boolean>}
*/
validate(data: BlockToolData): Promise<boolean>;

/**
* Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback
* Can be useful for block changes invisible for editor core.
*/
dispatchChange(): void;
}