diff --git a/.travis.yml b/.travis.yml index 119670a3..0aef5aa1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,16 @@ language: node_js sudo: false node_js: - - "0.12" + - '0.12' before_script: - - "npm update -g npm" - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" - - "npm install -g grunt-cli" + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start + - npm install -g grunt-cli + +notifications: + email: false + slack: + secure: RVZTvjJhyjbZ+z7D7enUNWMBuHW6It9+33ArMcO1RbfuwzlA5aeQl+PnpDNNYITnEig1xOoSs4blBj7rLSJlC9xigLS8qzsE8Q+SLY6dvXRZ6l0dmIaduwijO0f5sPsd2neoDN3fFihlWhQKBuU/+3R9zRTfma3PS0nU1x5yHnM= + on_failure: change + on_success: change diff --git a/demo/build/app.js b/demo/build/app.js index 68342570..1526cfb9 100644 --- a/demo/build/app.js +++ b/demo/build/app.js @@ -38,7 +38,7 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ } config.$inject = ['$sceDelegateProvider', '$httpProvider', '$stateProvider', '$compileProvider', '$urlRouterProvider', 'demoMapProvider']; - app.constant('version', 'v0.13.0'); + app.constant('version', 'v0.13.1'); app.config(config); angular.element(document).ready(function() { @@ -253,123 +253,123 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ module.exports = { 'intro': { 'simple-example': { - url: getUrl('nudumu/4'), + url: getUrl('nudumu/6'), title: 'Simple example', description: 'Simple example' }, 'full-featured-demo': { - url: getUrl('xezevi/3'), + url: getUrl('xezevi/4'), title: 'Full featured demo', description: 'Full featured demo' } }, 'configuration': { 'configuration-by-object': { - url: getUrl('getazu/3'), + url: getUrl('getazu/4'), title: 'By `settings` object', description: 'Configuration by setting `settings` object' }, 'configuration-declarative-way': { - url: getUrl('jupeme/3'), + url: getUrl('jupeme/4'), title: 'In declarative way', description: 'Configuration in declarative way' } }, 'columns': { 'add-remove-column-ng-repeat': { - url: getUrl('muluto/4'), + url: getUrl('muluto/5'), title: 'Add/Remove (ng-repeat)', description: 'Add/Remove columns using ng-repeat' }, 'add-remove-column-by-attr': { - url: getUrl('xayeru/3'), + url: getUrl('xayeru/4'), title: 'Add/Remove (`columns` attribute)', description: 'Add/Remove columns using `columns` attribute' } }, 'binding': { 'data-binding': { - url: getUrl('lupile/4'), + url: getUrl('lupile/5'), title: 'Data binding', description: 'Data binding' }, 'settings-binding': { - url: getUrl('xaqasi/3'), + url: getUrl('xaqasi/4'), title: 'Table settings binding', description: 'Table settings binding' } }, 'callbacks': { 'callbacks-by-object': { - url: getUrl('nayito/5', 'html,js,console,output'), + url: getUrl('nayito/7', 'html,js,console,output'), title: 'By `settings` object', description: 'Listening callbacks using `settings` object' }, 'callbacks-declarative-way': { - url: getUrl('pucale/4', 'html,js,console,output'), + url: getUrl('pucale/5', 'html,js,console,output'), title: 'In declarative way', description: 'Listening callbacks in declarative way' } }, 'plugins': { 'copy-paste-context-menu': { - url: getUrl('zohoge/2'), + url: getUrl('zohoge/3'), title: 'Enable copy/paste in context menu', description: 'Enable copy/paste in context menu' } }, 'pagination': { 'rows-pagination': { - url: getUrl('fohohenabo/1'), + url: getUrl('rorozo/1'), title: 'Paginate rows', description: 'Paginate rows' }, 'columns-pagination': { - url: getUrl('qudufogafu/1'), + url: getUrl('kolerig/1'), title: 'Paginate columns', description: 'Paginate columns' }, }, 'other': { 'access-to-instance': { - url: getUrl('fovoxu/4'), + url: getUrl('fovoxu/5'), title: 'Access to Handsontable instance', description: 'Access to Handsontable instance' }, 'custom-validator': { - url: getUrl('qoweju/3'), + url: getUrl('qoweju/4'), title: 'Custom validator', description: 'Custom validator' }, 'custom-renderer': { - url: getUrl('locome/2'), + url: getUrl('locome/3'), title: 'Custom renderer', description: 'Custom renderer' }, }, 'PRO': { 'collapsing-columns-with-nested-headers': { - url: getUrl('wilani/3'), + url: getUrl('wilani/4'), title: 'Collapsing columns with nested headers', description: 'Create a nested, hierarchical structure of headers with expandable and collapsible columns' }, 'filtering-simple': { - url: getUrl('fijida/3'), + url: getUrl('fijida/4'), title: 'Data filtering (simple example)', description: 'Display rows that meet your criteria and hide the rest' }, 'filtering-external-inputs': { - url: getUrl('rewefa/9'), + url: getUrl('rewefa/10'), title: 'Data filtering (external inputs)', description: 'Display rows that meet your criteria and hide the rest' }, 'hiding-columns': { - url: getUrl('wapufa/2'), + url: getUrl('wapufa/3'), title: 'Hiding columns', description: 'Hide specific columns and show the rest' }, 'hiding-rows': { - url: getUrl('roximi/3'), + url: getUrl('roximi/4'), title: 'Hiding rows', description: 'Hide specific rows and show the rest' }, diff --git a/demo/js/demos.js b/demo/js/demos.js index 87166c30..d31715d9 100644 --- a/demo/js/demos.js +++ b/demo/js/demos.js @@ -12,123 +12,123 @@ module.exports = { 'intro': { 'simple-example': { - url: getUrl('nudumu/4'), + url: getUrl('nudumu/6'), title: 'Simple example', description: 'Simple example' }, 'full-featured-demo': { - url: getUrl('xezevi/3'), + url: getUrl('xezevi/4'), title: 'Full featured demo', description: 'Full featured demo' } }, 'configuration': { 'configuration-by-object': { - url: getUrl('getazu/3'), + url: getUrl('getazu/4'), title: 'By `settings` object', description: 'Configuration by setting `settings` object' }, 'configuration-declarative-way': { - url: getUrl('jupeme/3'), + url: getUrl('jupeme/4'), title: 'In declarative way', description: 'Configuration in declarative way' } }, 'columns': { 'add-remove-column-ng-repeat': { - url: getUrl('muluto/4'), + url: getUrl('muluto/5'), title: 'Add/Remove (ng-repeat)', description: 'Add/Remove columns using ng-repeat' }, 'add-remove-column-by-attr': { - url: getUrl('xayeru/3'), + url: getUrl('xayeru/4'), title: 'Add/Remove (`columns` attribute)', description: 'Add/Remove columns using `columns` attribute' } }, 'binding': { 'data-binding': { - url: getUrl('lupile/4'), + url: getUrl('lupile/5'), title: 'Data binding', description: 'Data binding' }, 'settings-binding': { - url: getUrl('xaqasi/3'), + url: getUrl('xaqasi/4'), title: 'Table settings binding', description: 'Table settings binding' } }, 'callbacks': { 'callbacks-by-object': { - url: getUrl('nayito/5', 'html,js,console,output'), + url: getUrl('nayito/7', 'html,js,console,output'), title: 'By `settings` object', description: 'Listening callbacks using `settings` object' }, 'callbacks-declarative-way': { - url: getUrl('pucale/4', 'html,js,console,output'), + url: getUrl('pucale/5', 'html,js,console,output'), title: 'In declarative way', description: 'Listening callbacks in declarative way' } }, 'plugins': { 'copy-paste-context-menu': { - url: getUrl('zohoge/2'), + url: getUrl('zohoge/3'), title: 'Enable copy/paste in context menu', description: 'Enable copy/paste in context menu' } }, 'pagination': { 'rows-pagination': { - url: getUrl('fohohenabo/1'), + url: getUrl('rorozo/1'), title: 'Paginate rows', description: 'Paginate rows' }, 'columns-pagination': { - url: getUrl('qudufogafu/1'), + url: getUrl('kolerig/1'), title: 'Paginate columns', description: 'Paginate columns' }, }, 'other': { 'access-to-instance': { - url: getUrl('fovoxu/4'), + url: getUrl('fovoxu/5'), title: 'Access to Handsontable instance', description: 'Access to Handsontable instance' }, 'custom-validator': { - url: getUrl('qoweju/3'), + url: getUrl('qoweju/4'), title: 'Custom validator', description: 'Custom validator' }, 'custom-renderer': { - url: getUrl('locome/2'), + url: getUrl('locome/3'), title: 'Custom renderer', description: 'Custom renderer' }, }, 'PRO': { 'collapsing-columns-with-nested-headers': { - url: getUrl('wilani/3'), + url: getUrl('wilani/4'), title: 'Collapsing columns with nested headers', description: 'Create a nested, hierarchical structure of headers with expandable and collapsible columns' }, 'filtering-simple': { - url: getUrl('fijida/3'), + url: getUrl('fijida/4'), title: 'Data filtering (simple example)', description: 'Display rows that meet your criteria and hide the rest' }, 'filtering-external-inputs': { - url: getUrl('rewefa/9'), + url: getUrl('rewefa/10'), title: 'Data filtering (external inputs)', description: 'Display rows that meet your criteria and hide the rest' }, 'hiding-columns': { - url: getUrl('wapufa/2'), + url: getUrl('wapufa/3'), title: 'Hiding columns', description: 'Hide specific columns and show the rest' }, 'hiding-rows': { - url: getUrl('roximi/3'), + url: getUrl('roximi/4'), title: 'Hiding rows', description: 'Hide specific rows and show the rest' }, diff --git a/dist/ngHandsontable.js b/dist/ngHandsontable.js index d4c75efc..3ab0642a 100644 --- a/dist/ngHandsontable.js +++ b/dist/ngHandsontable.js @@ -1,11 +1,11 @@ /** - * ng-handsontable 0.13.0 + * ng-handsontable 0.13.1 * * Copyright 2012-2015 Marcin Warpechowski * Copyright 2015 Handsoncode sp. z o.o. * Licensed under the MIT license. * https://github.com/handsontable/ngHandsontable - * Date: Wed Oct 26 2016 10:00:05 GMT+0200 (CEST) + * Date: Thu Aug 20 2020 11:07:09 GMT+0200 (CEST) */ if (document.all && !document.addEventListener) { // IE 8 and lower @@ -470,6 +470,10 @@ Handsontable.hooks.add('afterContextMenuShow', function() { settingFactory.updateHandsontableSettings($scope.hotInstance, $scope.htSettings); }; this.removeColumnSetting = function(column) { + if (!$scope.hotInstance) { + return; + } + if ($scope.htSettings.columns.indexOf(column) > -1) { $scope.htSettings.columns.splice($scope.htSettings.columns.indexOf(column), 1); settingFactory.updateHandsontableSettings($scope.hotInstance, $scope.htSettings); @@ -597,6 +601,24 @@ Handsontable.hooks.add('afterContextMenuShow', function() { settingFactory.updateHandsontableSettings(scope.hotInstance, scope.htSettings); } }); + + function destroyInstance() { + if (scope.hotInstance) { + scope.hotInstance.destroy(); + scope.hotInstance = null; + scope.htSettings = {}; + } + } + + // Destroy triggered by controller or scope destroying + scope.$on('$destroy', function() { + destroyInstance(); + }); + + // Destroy triggered by DOM element removing + element.on('$destroy', function() { + destroyInstance(); + }); }; } }; diff --git a/dist/ngHandsontable.min.js b/dist/ngHandsontable.min.js index 0819e402..abad02f8 100644 --- a/dist/ngHandsontable.min.js +++ b/dist/ngHandsontable.min.js @@ -1,11 +1,11 @@ /** - * ng-handsontable 0.13.0 + * ng-handsontable 0.13.1 * * Copyright 2012-2015 Marcin Warpechowski * Copyright 2015 Handsoncode sp. z o.o. * Licensed under the MIT license. * https://github.com/handsontable/ngHandsontable - * Date: Wed Oct 26 2016 10:00:05 GMT+0200 (CEST) + * Date: Thu Aug 20 2020 11:07:09 GMT+0200 (CEST) */ -document.all&&!document.addEventListener&&(document.createElement("hot-table"),document.createElement("hot-column"),document.createElement("hot-autocomplete")),angular.module("ngHandsontable.services",[]),angular.module("ngHandsontable.directives",[]),angular.module("ngHandsontable",["ngHandsontable.services","ngHandsontable.directives"]),Handsontable.hooks.add("afterContextMenuShow",function(){Handsontable.eventManager.isHotTableEnv=!1}),function(){function a(a){return{parseAutoComplete:function(b,c,d){b.source=function(e,f){var g=this.instance.getSelected()[0],h=[],i=c[g];if(i){var j=b.optionList;if(j&&j.object){if(angular.isArray(j.object))h=j.object;else{var k=a(j.object)(i);if(angular.isArray(k))if(d)for(var l=0,m=k.length;l=0&&c.splice(c.indexOf("settings"),1),b&&(c=c.map(a)),c},getAvailableHooks:function(b){var c=Handsontable.hooks.getRegistered();return b&&(c=c.map(function(b){return"on-"+a(b)})),c}}}c.$inject=["hotRegisterer"],angular.module("ngHandsontable.services").factory("settingFactory",c)}(),function(){function a(){return{restrict:"EA",scope:!0,require:"^hotColumn",link:function(a,b,c,d){var e=c.datarows;d.setColumnOptionList(e)}}}a.$inject=[],angular.module("ngHandsontable.directives").directive("hotAutocomplete",a)}(),function(){function a(a){return{restrict:"EA",require:"^hotTable",scope:{},controller:["$scope",function(a){this.setColumnOptionList=function(b){a.column||(a.column={});var c={},d=b.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)\s*$/);d?(c.property=d[1],c.object=d[2]):c.object=b.split(","),a.column.optionList=c}}],compile:function(b,c){var d=this;return this.scope=a.trimScopeDefinitionAccordingToAttrs(a.getColumnScopeDefinition(),c),angular.forEach(Object.keys(this.scope),function(a){d.$$isolateBindings[a]={attrName:a,collection:!1,mode:"data"===a?"@":"=",optional:!1}}),function(b,c,d,e){var f={};angular.forEach(Object.keys(d),function(a){"$"!==a.charAt(0)&&""===d[a]&&(f[a]=!0)}),a.mergeSettingsFromScope(f,b),b.column||(b.column={}),angular.extend(b.column,f),e.setColumnSetting(b.column),b.$on("$destroy",function(){e.removeColumnSetting(b.column)})}}}}a.$inject=["settingFactory"],angular.module("ngHandsontable.directives").directive("hotColumn",a)}(),function(){function a(a,b,c,d){return{restrict:"EA",scope:{},priority:-400,controller:["$scope",function(b){this.setColumnSetting=function(c){b.htSettings||(b.htSettings={}),b.htSettings.columns||(b.htSettings.columns=[]),b.htSettings.columns.push(c),a.updateHandsontableSettings(b.hotInstance,b.htSettings)},this.removeColumnSetting=function(c){b.htSettings.columns.indexOf(c)>-1&&(b.htSettings.columns.splice(b.htSettings.columns.indexOf(c),1),a.updateHandsontableSettings(b.hotInstance,b.htSettings))}}],compile:function(e,f){var g,h=this;return this.scope=a.trimScopeDefinitionAccordingToAttrs(a.getTableScopeDefinition(),f),g=Object.keys(this.scope),angular.forEach(g,function(a){var b=h.scope[a].charAt(0);h.$$isolateBindings[a]={attrName:h.scope[a].length>1?h.scope[a].substr(1,h.scope[a].length):a,collection:"datarows"===a,mode:b,optional:!1}}),function(e,f,h){if(e.settings=d(h.settings)(e.$parent),e.htSettings||(e.htSettings={}),angular.forEach(Object.keys(h),function(a){"$"!==a.charAt(0)&&""===h[a]&&(e.htSettings[a]=!0)}),a.mergeSettingsFromScope(e.htSettings,e),a.mergeHooksFromScope(e.htSettings,e),e.htSettings.data||(e.htSettings.data=e.datarows),e.htSettings.dataSchema=e.dataschema,e.htSettings.hotId=h.hotId,e.htSettings.observeDOMVisibility=e.observeDomVisibility,e.htSettings.columns)for(var i=0,j=e.htSettings.columns.length;i=0)}),e.$watch("datarows",function(a){void 0!==a&&e.hotInstance.getSettings().data!==a&&e.hotInstance.loadData(a)}),e.$watchCollection("datarows",function(b,c){c&&c.length===e.htSettings.minSpareRows&&b.length!==e.htSettings.minSpareRows&&(e.htSettings.data=e.datarows,a.updateHandsontableSettings(e.hotInstance,e.htSettings))})}}}}a.$inject=["settingFactory","autoCompleteFactory","$rootScope","$parse"],angular.module("ngHandsontable.directives").directive("hotTable",a)}(); \ No newline at end of file +document.all&&!document.addEventListener&&(document.createElement("hot-table"),document.createElement("hot-column"),document.createElement("hot-autocomplete")),angular.module("ngHandsontable.services",[]),angular.module("ngHandsontable.directives",[]),angular.module("ngHandsontable",["ngHandsontable.services","ngHandsontable.directives"]),Handsontable.hooks.add("afterContextMenuShow",function(){Handsontable.eventManager.isHotTableEnv=!1}),function(){function a(a){return{parseAutoComplete:function(b,c,d){b.source=function(e,f){var g=this.instance.getSelected()[0],h=[],i=c[g];if(i){var j=b.optionList;if(j&&j.object){if(angular.isArray(j.object))h=j.object;else{var k=a(j.object)(i);if(angular.isArray(k))if(d)for(var l=0,m=k.length;l=0&&c.splice(c.indexOf("settings"),1),b&&(c=c.map(a)),c},getAvailableHooks:function(b){var c=Handsontable.hooks.getRegistered();return b&&(c=c.map(function(b){return"on-"+a(b)})),c}}}c.$inject=["hotRegisterer"],angular.module("ngHandsontable.services").factory("settingFactory",c)}(),function(){function a(){return{restrict:"EA",scope:!0,require:"^hotColumn",link:function(a,b,c,d){var e=c.datarows;d.setColumnOptionList(e)}}}a.$inject=[],angular.module("ngHandsontable.directives").directive("hotAutocomplete",a)}(),function(){function a(a){return{restrict:"EA",require:"^hotTable",scope:{},controller:["$scope",function(a){this.setColumnOptionList=function(b){a.column||(a.column={});var c={},d=b.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)\s*$/);d?(c.property=d[1],c.object=d[2]):c.object=b.split(","),a.column.optionList=c}}],compile:function(b,c){var d=this;return this.scope=a.trimScopeDefinitionAccordingToAttrs(a.getColumnScopeDefinition(),c),angular.forEach(Object.keys(this.scope),function(a){d.$$isolateBindings[a]={attrName:a,collection:!1,mode:"data"===a?"@":"=",optional:!1}}),function(b,c,d,e){var f={};angular.forEach(Object.keys(d),function(a){"$"!==a.charAt(0)&&""===d[a]&&(f[a]=!0)}),a.mergeSettingsFromScope(f,b),b.column||(b.column={}),angular.extend(b.column,f),e.setColumnSetting(b.column),b.$on("$destroy",function(){e.removeColumnSetting(b.column)})}}}}a.$inject=["settingFactory"],angular.module("ngHandsontable.directives").directive("hotColumn",a)}(),function(){function a(a,b,c,d){return{restrict:"EA",scope:{},priority:-400,controller:["$scope",function(b){this.setColumnSetting=function(c){b.htSettings||(b.htSettings={}),b.htSettings.columns||(b.htSettings.columns=[]),b.htSettings.columns.push(c),a.updateHandsontableSettings(b.hotInstance,b.htSettings)},this.removeColumnSetting=function(c){b.hotInstance&&b.htSettings.columns.indexOf(c)>-1&&(b.htSettings.columns.splice(b.htSettings.columns.indexOf(c),1),a.updateHandsontableSettings(b.hotInstance,b.htSettings))}}],compile:function(e,f){var g,h=this;return this.scope=a.trimScopeDefinitionAccordingToAttrs(a.getTableScopeDefinition(),f),g=Object.keys(this.scope),angular.forEach(g,function(a){var b=h.scope[a].charAt(0);h.$$isolateBindings[a]={attrName:h.scope[a].length>1?h.scope[a].substr(1,h.scope[a].length):a,collection:"datarows"===a,mode:b,optional:!1}}),function(e,f,h){function i(){e.hotInstance&&(e.hotInstance.destroy(),e.hotInstance=null,e.htSettings={})}if(e.settings=d(h.settings)(e.$parent),e.htSettings||(e.htSettings={}),angular.forEach(Object.keys(h),function(a){"$"!==a.charAt(0)&&""===h[a]&&(e.htSettings[a]=!0)}),a.mergeSettingsFromScope(e.htSettings,e),a.mergeHooksFromScope(e.htSettings,e),e.htSettings.data||(e.htSettings.data=e.datarows),e.htSettings.dataSchema=e.dataschema,e.htSettings.hotId=h.hotId,e.htSettings.observeDOMVisibility=e.observeDomVisibility,e.htSettings.columns)for(var j=0,k=e.htSettings.columns.length;j=0)}),e.$watch("datarows",function(a){void 0!==a&&e.hotInstance.getSettings().data!==a&&e.hotInstance.loadData(a)}),e.$watchCollection("datarows",function(b,c){c&&c.length===e.htSettings.minSpareRows&&b.length!==e.htSettings.minSpareRows&&(e.htSettings.data=e.datarows,a.updateHandsontableSettings(e.hotInstance,e.htSettings))}),e.$on("$destroy",function(){i()}),f.on("$destroy",function(){i()})}}}}a.$inject=["settingFactory","autoCompleteFactory","$rootScope","$parse"],angular.module("ngHandsontable.directives").directive("hotTable",a)}(); \ No newline at end of file diff --git a/package.json b/package.json index e4ecdbf0..1d9b187d 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "url": "https://github.com/handsontable/ngHandsontable/issues" }, "author": "Handsoncode ", - "version": "0.13.0", + "version": "0.13.1", "dependencies": { "angular": "^1.5.0", "handsontable": "^0.28.0" @@ -23,6 +23,7 @@ "generate-release": "^0.10.2", "grunt": "~0.4.5", "grunt-browserify": "^4.0.0", + "grunt-cli": "^1.3.2", "grunt-contrib-concat": "^1.0.0", "grunt-contrib-jshint": "^1.0.0", "grunt-contrib-uglify": "^0.11.0", diff --git a/src/directives/hotTable.js b/src/directives/hotTable.js index 2f9dc26a..d42164d9 100644 --- a/src/directives/hotTable.js +++ b/src/directives/hotTable.js @@ -20,6 +20,10 @@ settingFactory.updateHandsontableSettings($scope.hotInstance, $scope.htSettings); }; this.removeColumnSetting = function(column) { + if (!$scope.hotInstance) { + return; + } + if ($scope.htSettings.columns.indexOf(column) > -1) { $scope.htSettings.columns.splice($scope.htSettings.columns.indexOf(column), 1); settingFactory.updateHandsontableSettings($scope.hotInstance, $scope.htSettings); @@ -147,6 +151,24 @@ settingFactory.updateHandsontableSettings(scope.hotInstance, scope.htSettings); } }); + + function destroyInstance() { + if (scope.hotInstance) { + scope.hotInstance.destroy(); + scope.hotInstance = null; + scope.htSettings = {}; + } + } + + // Destroy triggered by controller or scope destroying + scope.$on('$destroy', function() { + destroyInstance(); + }); + + // Destroy triggered by DOM element removing + element.on('$destroy', function() { + destroyInstance(); + }); }; } }; diff --git a/test/directives/hotTable.spec.js b/test/directives/hotTable.spec.js index 8fa83e25..9a6c5672 100644 --- a/test/directives/hotTable.spec.js +++ b/test/directives/hotTable.spec.js @@ -14,7 +14,7 @@ describe('hotTable', function() { angular.element(document.querySelector('hot-table')).remove(); }); - it('should create Handsontable table', function() { + it('should create the Handsontable table', function() { var scope = angular.element(compile('')(rootScope)).isolateScope(); scope.$digest(); @@ -22,6 +22,23 @@ describe('hotTable', function() { expect(scope.hotInstance).toBeDefined(); }); + it('should destroy the Handsontable table when the scope is destroyed', function() { + var scope = angular.element(compile('')(rootScope)).isolateScope(); + + scope.$destroy(); + + expect(scope.hotInstance).toBeNull(); + }); + + it('should destroy the Handsontable table when the DOM element is removed', function() { + var element = angular.element(compile('')(rootScope)); + var scope = element.isolateScope(); + + element.remove(); + + expect(scope.hotInstance).toBeNull(); + }); + it('should re-render table after datarows change', function(done) { var afterRenderSpy = jasmine.createSpyObj('afterRender', ['callback']); rootScope.value = [['foo']];