Dependency Injection using aurelia_router.esm.js

@bigopon would you be so kind and give me a quick overview on how to go about DI using script ready bundles you put together? I would deeply appreciate it =)

1 Like

Here is a sandbox with many different kinds of container registration: string, class, instance etc… https://codesandbox.io/s/5x5o55nvnn

You can see that it’s not very different from what we normally do with the support of build tools. Hope that help.


Edit: I missed that you were asking specifically for ESM. So here is another: with `aurelia_router.esm.min.js’ https://codesandbox.io/s/n9826p2kzl

Still, things are not very different with our normal way.

1 Like

@bigopon you are the man!

I did something similar but my issue was this:

static inject = [MyService];

ESM did not like that. I did not realize you need it to code as:

static inject() { return [MyService]; }

Again, thank you so much!!!

@bigopon one more thing. Any reason why EventAggregator is not exported? I see its used within aurelia_rotuer.esm.js but its not part of the exported modules towards the bottom of the script…

The class static / instance field is on its way to standard, but atm it’s an error.

About EventAggregator: oops :sweat: I’ll add it soon

1 Like

@bigopon so since you re being the man and answering my questions… =)
Do you have some pointers on how to use the various decorators AU provides but without ‘@’ sign. I See that something like this can be done:

customElement("my-element")(MyElement);

computedFrom("firstName", "lastName")(
  MyElement,
  "fullName",
  Object.getOwnPropertyDescriptor(MyElement.prototype, "fullName")
);

How would you go about doing the same for @bindable decorator?

Im trying to pin point all this features so I can have a strong argument for my boss to allow us to use AU (showing it with ESM makes it quick way to demo it).

You have two way to declare bindables:

export class Combobox {
  static get $resource() {
    return {
      bindables: [
        /* short form */
        'items',
        /* full form */
        {
          name: 'selectedItem',
          defaultBindingMode: au.bindingMode.twoWay,
          /* or */
          defaultBindingMode: 'twoWay',
          changeHandler: 'bla bla bla'
        }
      ],
      /* for anything that is not custom element */
      type: 'attribute | valueConverter | bindingBehavior | viewEngineHooks',
      /* if it is a cutom attribute */
      templateController: 'Is it template controller' ? true : false,
      /* wanna do fancy thing? */
      processContent: () => {
        /* bla bla bla */
      }
    },
  }
}

2nd way:

export class Combobox {}
au.bindable('items')(Combobox);
au.bindable({ /* full form */)(Combobox);
1 Like

@bigopon bruh! Im loving the esm version, so flexible when using script type="module". Question: was it really painful to generate esm ready script for aurelia-router? Would it be dumb to try to do the same for aurelia-dialog, aurelia-validation, aurelia-store? Maybe each one of those plugins could import stuff like this: import { Container } from "./aurelia_router.esm.js" etc…

it’s pretty simple for umd version, something like this can be done (not done yet):

<script src='aurelia.umd.js'></script>
<script src='aurelia.dialog.js'></script>
<script src='aurelia.validation.js'></script>
<script>
  // to bootstrap
  aurelia.use
    .plugin(au.dialog.configure, { ... })
    .plugin(au.validation.configure, { ... })
</script>

I’m not sure about esm, seems quite hard without away to map to proper path for importing. There will probably be a build service app, for you to decide which goes into bundle, probably something like this

Question: was it really painful to generate esm ready script for aurelia-router?

No it was not, it was pretty simple actually. It’s just how to do it intuitively that was hard to solve. We can have 10 different dists like: aurelia_router_dialog aurelia_route_dialog_validation, aurelia_validation_younameit but I don’t know if any one will like it.

Is this service app something you are working on? Is this what you used for creating the current bundles?

It’s in my plan. It’s an old prototype of many current features, like static resources convention and umd bundle. If needed, you can have a look at index.js and index.full.js in https://github.com/aurelia/script/tree/master/build so you can have a clue how to build a custom one

@bigopon thanks for the link. I ll play around with if to see if I can get aurelia-validation bundled. You are the man! MVP in my book =)

@bigopon take a look at this repo when you have a chance. This is something just to play around with. It contains validation, dialog and store baked in. For dialog, I only included the service, controller and render, I never use the defaults. This gives me pretty much everything I need to demo functionality using esm =)

Again, thank you for pointing me to the right place!!!

Hey @AlbertoDePena, how would you register the dialog with dialog defaults?

I had issues when registering the defaults. The issues were related to the way the resources are loaded for dialog defaults. That is way I dont use them (I dont really ever needed to). I had extract the auto-focus custom attribute. I think it can be done but might have to change the URL for the resources =/

Okay, that makes sense. Would you mind showing me how you are using the Dialog in a simple sample app?

Take a look at this super simple “demo app” https://github.com/AlbertoDePena/aurelia-script/blob/master/src/main.js

I am not using the dialog but I do register is, the rest would work the same as described in the Aurelia docs for the dialog plugin =)

Okay, so I am trying the following in my home.js:

import {DialogService} from '../../../lib/aurelia.full.esm.js';

export class Home {
  static inject() {
    return [DialogService];
  }
  constructor(dialogSvc) {
    this.dialogSvc = dialogSvc;
  }
  showDialog() {
    let model = {};
    this.dialogSvc.open({ viewModel: ConfirmDialog, model: model, lock: false });
  }
}

When I try to test by calling the showDialog() function, I get the following error:

Error: Can not resolve "moduleId" of "ConfirmDialog".
    at DialogService.ensureViewModel (aurelia.full.esm.js:27393)
    at DialogService.open (aurelia.full.esm.js:27464)
    at Home.showDialog (home.js:30)
    at CallScope.evaluate (aurelia.full.esm.js:3637)
    at Listener.callSource (aurelia.full.esm.js:7146)
    at Listener.handleEvent (aurelia.full.esm.js:7155)
    at HTMLDocument.handleDelegatedEvent (aurelia.full.esm.js:5220)

I know the ConfirmDialog is importing correctly when I debug it.

The ConfirmDialog looks like the following:

import {DialogController} from '../../lib/aurelia.full.esm.js';

export class ConfirmDialog {
  static inject() {
    return [DialogController];
  }
  constructor(controller) {
    this.controller = controller;
  }
  activate(model) {
      this.model = model;
  }
  ok(value) {
    this.controller.ok(value);
  }
  cancel() {
    this.controller.cancel();
  }
}

Do you see anything wrong with what I am doing?

You have to import ConfirmDialog in the Home class…

import { ConfirmDialog } from './path-to-confirm-dialog';

Oops, I already had that in my code. Sorry for not copying the top line:

import {ConfirmDialog} from '../../dialogs/confirm-dialog.js';

So you can see that I have it imported. Sorry about missing that in my original snippet.

It still gives me the same error.