| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import BasePlugin from './../_base';
- import jsonpatch from './../../../lib/jsonpatch/json-patch-duplex';
- import DataObserver from './dataObserver';
- import {arrayEach} from './../../helpers/array';
- import {registerPlugin} from './../../plugins';
- // Handsontable.hooks.register('afterChangesObserved');
- /**
- * @plugin ObserveChanges
- *
- * @description
- * This plugin allows to observe data source changes.
- *
- * By default, the plugin is declared as `undefined`, which makes it disabled.
- * Enabling this plugin switches the table into one-way data binding where changes are applied into the data source (outside from the table)
- * will be automatically reflected in the table.
- *
- * ```js
- * ...
- * // as a boolean
- * observeChanges: true,
- * ...
- * ```
- *
- * To configure this plugin see {@link Options#observeChanges}.
- */
- class ObserveChanges extends BasePlugin {
- constructor(hotInstance) {
- super(hotInstance);
- /**
- * Instance of {@link DataObserver}.
- *
- * @type {DataObserver}
- */
- this.observer = null;
- }
- /**
- * Check if the plugin is enabled in the handsontable settings.
- *
- * @returns {Boolean}
- */
- isEnabled() {
- return this.hot.getSettings().observeChanges;
- }
- /**
- * Enable plugin for this Handsontable instance.
- */
- enablePlugin() {
- if (this.enabled) {
- return;
- }
- if (!this.observer) {
- this.observer = new DataObserver(this.hot.getSourceData());
- this._exposePublicApi();
- }
- this.observer.addLocalHook('change', (patches) => this.onDataChange(patches));
- this.addHook('afterCreateRow', () => this.onAfterTableAlter());
- this.addHook('afterRemoveRow', () => this.onAfterTableAlter());
- this.addHook('afterCreateCol', () => this.onAfterTableAlter());
- this.addHook('afterRemoveCol', () => this.onAfterTableAlter());
- this.addHook('afterChange', (changes, source) => this.onAfterTableAlter(source));
- this.addHook('afterLoadData', (firstRun) => this.onAfterLoadData(firstRun));
- super.enablePlugin();
- }
- /**
- * Disable plugin for this Handsontable instance.
- */
- disablePlugin() {
- if (this.observer) {
- this.observer.destroy();
- this.observer = null;
- this._deletePublicApi();
- }
- super.disablePlugin();
- }
- /**
- * Data change observer.
- *
- * @private
- * @param {Array} patches An array of objects which every item defines coordinates where data was changed.
- */
- onDataChange(patches) {
- if (!this.observer.isPaused()) {
- const sourceName = `${this.pluginName}.change`;
- const actions = {
- add: (patch) => {
- if (isNaN(patch.col)) {
- this.hot.runHooks('afterCreateRow', patch.row, 1, sourceName);
- } else {
- this.hot.runHooks('afterCreateCol', patch.col, 1, sourceName);
- }
- },
- remove: (patch) => {
- if (isNaN(patch.col)) {
- this.hot.runHooks('afterRemoveRow', patch.row, 1, sourceName);
- } else {
- this.hot.runHooks('afterRemoveCol', patch.col, 1, sourceName);
- }
- },
- replace: (patch) => {
- this.hot.runHooks('afterChange', [patch.row, patch.col, null, patch.value], sourceName);
- },
- };
- arrayEach(patches, (patch) => {
- if (actions[patch.op]) {
- actions[patch.op](patch);
- }
- });
- this.hot.render();
- }
- this.hot.runHooks('afterChangesObserved');
- }
- /**
- * On after table alter listener. Prevents infinity loop between internal and external data changing.
- *
- * @private
- * @param source
- */
- onAfterTableAlter(source) {
- if (source !== 'loadData') {
- this.observer.pause();
- this.hot.addHookOnce('afterChangesObserved', () => this.observer.resume());
- }
- }
- /**
- * On after load data listener.
- *
- * @private
- * @param {Boolean} firstRun `true` if event was fired first time.
- */
- onAfterLoadData(firstRun) {
- if (!firstRun) {
- this.observer.setObservedData(this.hot.getSourceData());
- }
- }
- /**
- * Destroy plugin instance.
- */
- destroy() {
- if (this.observer) {
- this.observer.destroy();
- this._deletePublicApi();
- }
- super.destroy();
- }
- /**
- * Expose plugins methods to the core.
- *
- * @private
- */
- _exposePublicApi() {
- const hot = this.hot;
- hot.pauseObservingChanges = () => this.observer.pause();
- hot.resumeObservingChanges = () => this.observer.resume();
- hot.isPausedObservingChanges = () => this.observer.isPaused();
- }
- /**
- * Delete all previously exposed methods.
- *
- * @private
- */
- _deletePublicApi() {
- const hot = this.hot;
- delete hot.pauseObservingChanges;
- delete hot.resumeObservingChanges;
- delete hot.isPausedObservingChanges;
- }
- }
- export default ObserveChanges;
- registerPlugin('observeChanges', ObserveChanges);
|