# ES6 module pre-injection

**URL:** <https://discourse.aurelia.io/t/es6-module-pre-injection/3940>\
**Category:** Framework Knowledge\
**Created:** [December 19, 2020, 4:55pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940 "2020-12-19T16:55:36Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kremnari](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/kremnari/32/2177_2.png) [@Kremnari](https://discourse.aurelia.io/u/Kremnari)\
**Post date:** [December 19, 2020, 4:55pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/1 "2020-12-19T16:55:36Z")

</div>

I think I’m missing a key concept.

I created a wrapper for aurelia-dialog, that gets the DialogService injected.  
I’m also utilizing (as bad practice and as temp scaffolding) a “managers object” to pass around that should contain a reference to my DialogMgr  
[link@line 19](https://github.com/Kremnari/TheFactoryMustGrow/blob/95a4670a7bc8e5b6a722d21027c6b946d4f65283/src/managers.js)  
However, the DialogMgr property after page load, only contains the reference to the constructor, not the post-injection singleton that aurelia normally creates.

I can, in my app.js after loading, reassign the property through that dependency injection. I’m curious what I’m missing that prevents my `const mgrs` from having the instantiated object.

---

<div class="post-metadata">

**Author:** ![Sayan751](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sayan751/32/1861_2.png) [@Sayan751](https://discourse.aurelia.io/u/Sayan751)\
**Post date:** [December 19, 2020, 8:45pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/2 "2020-12-19T20:45:46Z")

</div>

@Kremnari Why not convert the `mgrs` object to a class and inject the `DialogMgr` instance via constructor? That way you can also inject the singleton `mgrs` in your other classes.

However, the bigger question IMO is why you need such a pattern. Why not directly injection the instances to the classes as per the need? Why do you need this wrapper object?

---

<div class="post-metadata">

**Author:** ![Kremnari](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/kremnari/32/2177_2.png) [@Kremnari](https://discourse.aurelia.io/u/Kremnari)\
**Post date:** [December 19, 2020, 11:00pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/3 "2020-12-19T23:00:22Z")

</div>

I was initially passing around the individual `mgrs` to constructors but that seemed both tedious and unnecessary with dependency injection. I didn’t form it as it’s own class as I didn’t need it as anything other than an object literal (container). As it exists, I don’t even need to inject it, I just import it into global scope.

The wrapper object for dialog allows me to use it like  
`await mgrs.DS.open("SelectBus", {base: mgrs.baseApp})`,  
IE await simplicity… just looking at it, I should be able to simplify it further to something like  
`await mgrs.DS.SelectBus(paramObj)`

My code style is still developing 😃 While there is some guidance for game patterns, there’s still a lot of grey areas that depend largely on what is being developed, and the mechanics I wanted were merely broad-stroked in the beginning.

But more to the point, I’m curious about the instantiation mechanics at play. In the object literal, I cannot assign the module export, nor use `new` and get a class instance _with_ the injected dependency. How, and when, might the `inject` be executing to create the au’s DI version of the class?

---

<div class="post-metadata">

**Author:** ![Sayan751](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sayan751/32/1861_2.png) [@Sayan751](https://discourse.aurelia.io/u/Sayan751)\
**Post date:** [December 20, 2020, 1:08pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/4 "2020-12-20T13:08:31Z")

</div>

IMO injecting the instances vis ctor makes it easier to test the components. Testing with your pattern might get tricky.

If testing is not a concern for you then, you can create your `mgrs` object literal after aurelia is started. For that you can do something like this.

```auto
// this goes to your main.js 
mgrs = {
//...
DS: Container.instance.get(DialogMgr)
//...
}

```

---

<div class="post-metadata">

**Author:** ![Kremnari](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/kremnari/32/2177_2.png) [@Kremnari](https://discourse.aurelia.io/u/Kremnari)\
**Post date:** [December 20, 2020, 5:47pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/5 "2020-12-20T17:47:16Z")

</div>

> [@Sayan751](#):
>
> ```auto
> // this goes to your main.js 
> mgrs = {
> //...
> DS: Container.instance.get(DialogMgr)
> //...
> }
> 
> ```

This is effectively what I’m doing, just adding that property in my main.js.

Your statement of “after aurelia is started,” is kind of the key I’m trying to understand. The `inject` process is dependent on aurelia being ‘started;’ where are the details of that lifecycle? When does inject actually do it’s processing?

---

<div class="post-metadata">

**Author:** ![Sayan751](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sayan751/32/1861_2.png) [@Sayan751](https://discourse.aurelia.io/u/Sayan751)\
**Post date:** [December 20, 2020, 6:12pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/6 "2020-12-20T18:12:50Z")

</div>

That actually is dependent on how DI is instantiating the components. `@inject` is just working as the metadata provider (in this case the dependency information provider). In short, the components instantiated as per dependency graph (from view and view-model), and during instantiation, the DI injects the deps to class ctor, as per the info provided by `@inject`/`@autoinject`. This is ofc a simplified version.

Now the reason, I mentioned to do this “after aurelia is started”, is because, we want all the initializations work from every plugin to be completed, before you request for an instance to the DI. Otherwise you may end up with an “invalid” instance of the class. With Aurelia1 the DI and the Contracts are based on `abstract` classes. So until everything is properly initialized (which is surely done after `aurelia.start()` is resolved), asking the Container for an instance of class may result error, as that might try return an instance of the abstract class, which is certainly not intended.

Hope this makes sense.

---

<div class="post-metadata">

**Author:** ![elitemike](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/elitemike/32/690_2.png) [@elitemike](https://discourse.aurelia.io/u/elitemike)\
**Post date:** [December 26, 2020, 5:40pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/7 "2020-12-26T17:40:25Z")

</div>

I’m not sure what your needs are, but I created a wrapper class around aurelia-dialog for my needs. It lets me do things like this. I built in a good bit of options that work in my application like auto close, the ability to change the footer if needed on the custom dialogs. Aurelia dialog was a great starting point, but I’ve often considered scrapping it in favor of a full custom implementation.

alerts

```auto
let alert1 = this.dialogFactory.alert("Alert 1 title", "alert content", { allowEscapeToDismiss: true });

```

confirm

```auto
 let result = await this.dialogFactory.confirm("Simple confirm", "It doesn't get any easier than this");

```

custom view models

```auto
let settings: CustomSettings<CustomDemoModel> = {
      viewModel: CustomBody,
      model: { name: "Joe Smith" }
    };

let result = await this.dialogFactory.custom<CustomDemoModel, CustomDemoResult>("My custom", settings);

```

The custom view and view Model for the above

```auto

import { CustomDemoResult } from "./customDemoResult";
import { DialogContainerBase, DialogOkArgs } from "dialog-factory";

export class CustomBody extends DialogContainerBase<CustomDemoModel> {
  public async ok(args: DialogOkArgs) {
    let result = new CustomDemoResult();
    result.newName = this.model.name;
    await this.doWork();
    return result;
  }

  doWork(): Promise<void> {
    return new Promise<void>((resolve) => {
      setTimeout(() => {
        resolve();
      }, 50);
    });
  }
}

export class CustomDemoModel {
  public name: string = null;
}

```

```auto
<template>
    <dialog-container>
        <div slot="body">
            <div class="form-group">
                <label for="nameField">Name</label>
                <input class="form-control" value.bind="model.name" type="text" id="nameField" />
            </div>
        </div>
    </dialog-container>
</template>

```

---

<div class="post-metadata">

**Author:** ![Kremnari](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/kremnari/32/2177_2.png) [@Kremnari](https://discourse.aurelia.io/u/Kremnari)\
**Post date:** [December 29, 2020, 2:10pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/8 "2020-12-29T14:10:37Z")

</div>

> [@Sayan751](#):
>
> @Kremnari Why not convert the `mgrs` object to a class and inject the `DialogMgr` instance via constructor? That way you can also inject the singleton `mgrs` in your other classes.

I’ve been working on my code, and finally remember the right response to this. The reason my mgrs object isn’t a class, is so I can just import it into the relevant files. As a class (or au-strapped class) it would need to be instantiated and/or injected to be used. As it exists, I can use it freely by reference `mgrs.yadda.yadda` without having to store it. This improves the visibility of the object as it doesn’t require a `this`.

---

<div class="post-metadata">

**Author:** ![Bart](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bart/32/1878_2.png) [@Bart](https://discourse.aurelia.io/u/Bart)\
**Post date:** [December 30, 2020, 6:00pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/9 "2020-12-30T18:00:15Z")

</div>

I understand your reasoning regarding putting your `mgrs` object in the global scope. At first glance, making it generally available in your components that way might indeed seem to be easy and straightforward.

However, Sayan751 made an interesting point:

> IMO injecting the instances vis ctor makes it easier to test the components. Testing with your pattern might get tricky.

Suppose you want to create automated tests (like unit tests or so) to make sure that the internal logic of your components will not break when you start adding features or fix some bugs. If your components are secretly dependent on objects in the global scope, like your global `mgrs` object, creating tests will become very tricky, since those tests will probably need to address such global objects as well. When you inject external dependencies (like your `mgrs` object) via the constructor, your components’ external dependencies are not only more transparent, but also much easier to replace with a dummy/mock object that is suitable for your automated tests at hand.

Testing is just one example. In general, you actually don’t want dependencies you can’t control very well during runtime (like dependencies on objects in the global scope). Those might introduce unclear and unexpected side effects in the long term and make debugging a nightmare. And avoiding global objects will also keep the global space clean, which is always a good thing. What would happen if certain global objects required by component A would conflict with certain global objects required by component B? Or even worse: with certain global objects that are internally created by the Aurelia framework? (I don’t know if there are any important global objects created by the Aurelia framework, but I really don’t want to find out the hard way…)

In short: using dependency injection (and avoiding global objects) will promote loose coupling between your classes/components and ease testing, thus resulting in a more robust and more flexible codebase.

[https://www.w3.org/wiki/JavaScript\_best\_practices#Avoid\_globals](https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals)

---

<div class="post-metadata">

**Author:** ![Sayan751](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/sayan751/32/1861_2.png) [@Sayan751](https://discourse.aurelia.io/u/Sayan751)\
**Post date:** [December 30, 2020, 9:18pm UTC](https://discourse.aurelia.io/t/es6-module-pre-injection/3940/10 "2020-12-30T21:18:24Z")

</div>

Well explained! The `mgrs` in this case however is still exposed via a JS module, so it might not pollute the “global” space in “true” sense, but all other arguments related to testing, and coupling still holds.

Especially for testing, you don’t want to share a “global” object across all your tests, as that might potentially result in residual state from previous test. And it’s very very scary, when the tests starts failing randomly!!
