Search code examples
typescriptdependency-injectionaureliaaurelia-dialog

Unable to inject class with DI


I have a class that uses an instance of DialogService from 'aurelia-dialog` to open almost every dialog in my Aurelia application. In a very abstract way the class looks like this:

export class DialogTrigger{
    triggerDialogA() {...}
    triggerDialogB() {...}
    triggerDialogC() {...}
}

Everything works fine until I try to inject DialogTrigger to one of the dialogs.

So let's say that I want to create a new dialog, DialogD. I simply add another method triggerDialogD() in DialogTrigger that opens a new dialog with a DialodD view model and everything works. But if I want my new dialog to also trigger one of the other dialogs (A,B or C) by using an instance of DialogTrigger everything falls apart.

If I inject DialogTrigger into DialogD I always get an error:

key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?

If I remove the dependency, the dialog works.

TL;DR I have a DialogTrigger class that opens aurelia-dialogs. DI fails when I inject DialogTrigger to any dialog instantiated by it.

Any ideas?


Solution

  • Sounds like a circular dependency issue.

    You would have to use path strings to reference the dialogs inside DialogTrigger. You cannot import the Dialog into DialogTrigger and then also import DialogTrigger into the Dialog.


    This would work:

    import { DialogService } from 'aurelia-dialog';
    
    export class DialogTrigger {
      static inject = [DialogService];
    
      constructor(dialogService) {
        this._dialogService = dialogService;
      }
    
      openDialogA() { this._dialogService.open({ viewModel: './prompt' }); }
      openDialogB() { this._dialogService.open({ viewModel: './prompt' }); }
    }
    

    This WILL NOT work:

    import { DialogService } from 'aurelia-dialog';
    import { Prompt } from './prompt';
    
    export class DialogTrigger {
      static inject = [DialogService];
    
      constructor(dialogService) {
        this._dialogService = dialogService;
      }
    
      openDialogA() { this._dialogService.open({ viewModel: Prompt }); }
      openDialogB() { this._dialogService.open({ viewModel: Prompt }); }
    }
    

    Another option is to pass the reference to DialogTrigger in the open() function's model: {} parameter. Like so:

    this._dialogService.open({ viewModel: './prompt', model: { dialogTrigger: this }  });