akserg / ng2-dnd

Angular 2 Drag-and-Drop without dependencies
MIT License
839 stars 252 forks source link

ViewDestroyedError: Attempt to use a destroyed view: detectChanges #177

Open tsu-la opened 7 years ago

tsu-la commented 7 years ago

So I discovered this issue while working with items that are observable. The error is generated after the onDropSuccess is called. It seems that the method or the reference to the events are not released after the view is recreated.
I think this should be easy to fix by adding a simple ngOndestroy and unsubscribing to the events.

When dropping an item that has data no error is created.

  1. Drop item with dragData onto sortable div.
  2. call the (onDropSuccess)="onItemDrop($event)"
  3. In the method onItemDrop push another item into the array of observable objects. that are in the sortable container.

Receive error:

ERROR Error: ViewDestroyedError: Attempt to use a destroyed view: detectChanges at viewDestroyedError (http://localhost:3000/vendor.dll.js:46682:12) at Object.debugUpdateDirectives [as updateDirectives] (http://localhost:3000/vendor.dll.js:51292:15) at checkAndUpdateView (http://localhost:3000/vendor.dll.js:50475:14) at callWithDebugContext (http://localhost:3000/vendor.dll.js:51695:42) at Object.debugCheckAndUpdateView [as checkAndUpdateView] (http://localhost:3000/vendor.dll.js:51235:12) at ViewRef_.vendor../nodemodules/@angular/core/@angular/core.es5.js.ViewRef.detectChanges (http://localhost:3000/vendor.dll.js:48406:18) at http://localhost:3000/index.js:34157:24 at ZoneDelegate.polyfill../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:3000/polyfill.dll.js:18607:31) at Object.onInvokeTask (http://localhost:3000/vendor.dll.js:42120:33) at ZoneDelegate.polyfill../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:3000/polyfill.dll.js:18606:36) at ____Elapsed_1847_msAtMon_Jul_31_2017_09_39_59_GMT_0400__Eastern_DaylightTime (http://localhost) at Object.onScheduleTask (http://localhost:3000/polyfill.dll.js:18110:22) at ZoneDelegate.polyfill../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask (http://localhost:3000/polyfill.dll.js:18587:51) at Object.onScheduleTask (http://localhost:3000/polyfill.dll.js:18483:29) at ZoneDelegate.polyfill../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask (http://localhost:3000/polyfill.dll.js:18587:51) at Zone.polyfill../node_modules/zone.js/dist/zone.js.Zone.scheduleTask (http://localhost:3000/polyfill.dll.js:18418:43) at Zone.polyfill../node_modules/zone.js/dist/zone.js.Zone.scheduleMacroTask (http://localhost:3000/polyfill.dll.js:18441:25) at http://localhost:3000/polyfill.dll.js:19759:33 at proto.(anonymous function) (http://localhost:3000/polyfill.dll.js:19609:20)

anasAsh commented 7 years ago

duplicates #156.

tsu-la commented 7 years ago

is this one #156. going to be merged into master soon?

anasAsh commented 7 years ago

the reason that this issue is happening that you are deleting the reference on the sortableData or dragableData on the change event. in abstract class, the detectChange method is waiting for 250 ms before firing the change detect, at that time your view and component will be destroyed.

    detectChanges() {
        // Programmatically run change detection to fix issue in Safari
        setTimeout(() => {
            this._cdr.detectChanges();
        }, 250);
    }

a workaround for this is to let your component to wait for more than 250 ms before applying the change when receiving an event.

tsu-la commented 7 years ago

Thanks, is this something that will be added to master?

anasAsh commented 7 years ago

i don't know, am not the author of this repo and i didn't find a better solution to make a merge request.

tsu-la commented 7 years ago

So I was able to fix the issue and #156 but I am unable to push my changes up on a new branch or create a pull request. This is in the AbstractComponent. . Is there away I can get this into master? Thanks The code that resolved these issues is below: ` /*** Change detection **/

detectChanges () {
    // Programmatically run change detection to fix issue in Safari
    setTimeout(() => {
        if ( this._cdr !== null &&
            this._cdr !== undefined &&
            ! (this._cdr as ViewRef_).destroyed ) {
                this._cdr.detectChanges();
        }

    }, 250);
}`