angular: Pipes break when used in a ng-switch-default

When using a custom pipe inside of an ng-switch-default the pipe breaks with the exception:

EXCEPTION: TypeError: Cannot read property 'constructor' of undefined in [null]

TypeError: Cannot read property 'constructor' of undefined
    at Object.implementsOnDestroy (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:7655:16)
    at Function.ChangeDetectionUtil.callPipeOnDestroy (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:16480:38)
    at AbstractChangeDetector.ChangeDetector_Hello_5.dehydrateDirectives (eval at <anonymous> (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:20571:14), <anonymous>:93:49)
    at AbstractChangeDetector.dehydrate (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:20384:12)
    at AppViewManagerUtils.dehydrateView (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:17481:35)
    at AppViewManager_._viewDehydrateRecurse (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:21117:21)
    at AppViewManager_._destroyViewInContainer (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:21105:12)
    at AppViewManager_.destroyViewInContainer (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:21060:12)
    at ViewContainerRef_.remove (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:9707:24)
    at ViewContainerRef_.ViewContainerRef.clear (https://code.angularjs.org/2.0.0-alpha.45/angular2.dev.js:9632:14)BrowserDomAdapter.logError @ angular2.dev.js:21984ExceptionHandler.call @ angular2.dev.js:4439(anonymous function) @ angular2.dev.js:19685NgZone._notifyOnError @ angular2.dev.js:10746errorHandling.onError @ angular2.dev.js:10654run @ angular2.dev.js:141(anonymous function) @ angular2.dev.js:10678zoneBoundFn @ angular2.dev.js:111lib$es6$promise$asap$$flush @ angular2.dev.js:1301
2015-11-06 15:24:17.011 angular2.dev.js:21984 ERROR CONTEXT:BrowserDomAdapter.logError @ angular2.dev.js:21984ExceptionHandler.call @ angular2.dev.js:4442(anonymous function) @ angular2.dev.js:19685NgZone._notifyOnError @ angular2.dev.js:10746errorHandling.onError @ angular2.dev.js:10654run @ angular2.dev.js:141(anonymous function) @ angular2.dev.js:10678zoneBoundFn @ angular2.dev.js:111lib$es6$promise$asap$$flush @ angular2.dev.js:1301

Here is a plunker: http://plnkr.co/edit/PSRVVPtbl6MzRzNPzc2b?p=preview When I remove the ng-switch-default template, I don’t get the error.

Using Chrome 46 on Mac.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 10
  • Comments: 21 (5 by maintainers)

Commits related to this issue

Most upvoted comments

@laurelnaiad Figured it out

<script src="node_modules/systemjs/dist/system.src.js"></script>
    <script>
        System.register("angular2/src/core/change_detection/pipe_lifecycle_reflector", [], true, function(require, exports, module) {
            exports.implementsOnDestroy = function(pipe) { return pipe ? pipe.constructor.prototype.ngOnDestroy : false };
        });
    </script>

This did it for me.

I simplified @Xesued’s reproduction – no custom pipe appears needed, just ensure ngFor keeps an unused branch so it tries to destroy a pipe that didn’t get initialized. I wasn’t able to reproduce with @Ristaaf’s optional pipe though. I’m a bit confused though, since in @Xesued’s example all ngFor branches do get used by different entries… but the common thread seems sorta clear.

So the crash occurs here, due to pipe ending up undefined. I think this could be patched as follows:

function implementsOnDestroy(pipe: any): boolean {
    // return pipe.constructor.prototype.ngOnDestroy;
    return pipe ? pipe.constructor.prototype.ngOnDestroy : false;
}

(For debugging I also tried to add a print statement in the parent stack level; here selectedPipe turned out as {}😃

    ChangeDetectionUtil.callPipeOnDestroy = function (selectedPipe) {
        console.log('callPipeOnDestroy:selectedPipe', selectedPipe);
        if (pipe_lifecycle_reflector_1.implementsOnDestroy(selectedPipe.pipe)) {
            selectedPipe.pipe.ngOnDestroy();
        }
    };

I’m having trouble locally running the tests to verify this null check fixes the issue without messing up other things though; perhaps someone else would be able to try that…

Edit: to clarify, I haven’t verified if suppressing the error makes things work as desired; on my own code I still had an unrelated error I was already getting on other code as well, while with Plunker I’m not sure I can just alter the ng2 code like this, so I haven’t actually seen the result.