# How do you create Aurelia plugins?

**URL:** <https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902>\
**Category:** Help Requests\
**Created:** [November 16, 2018, 2:55am UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902 "2018-11-16T02:55:32Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ArchEnemy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/archenemy/32/2445_2.png) [@ArchEnemy](https://discourse.aurelia.io/u/ArchEnemy)\
**Post date:** [November 16, 2018, 2:55am UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902/1 "2018-11-16T02:55:32Z")

</div>

I’ve identified a need to build a custom element that probably needs to be turned into a plugin (so others can use it). I was wondering if there was a way to write my custom component, put it in a folder, and then publish it to npm somehow. Haven’t quite figured it out and couldn’t find any guides.

I do see that plugins don’t have to be overly complex (at least from what I see in my node\_modules aurelia plugins), but setting it up as a project does seem to be.

Right now I’m trying to figure out the bindingEngine feature because my plugin may require (essentially Angular 1.x watchers) on a big array of objects (So I don’t think I can use bindable/observable). I need basically either (a) a javascript class that has javascript code that the user enters or modifies and it affects the plugin component custom element. OR (b) a big giant JSON object array that the user can customize completely.

I can see that “ag-grid” plugin has decided to use like 40 bindables… so maybe I should do that?

Then after I build a folder: /myplugin/, myplugin.js, myplugin.html . I want to maybe run some command like “au generate plugin” (Just maybe write up a package.json and a few other things and it’s ready? e.g. [https://docs.npmjs.com/creating-node-js-modules](https://docs.npmjs.com/creating-node-js-modules) )

Or am I supposed to be making a “feature” I dont know. Plugin vs feature thing is confusing nomenclature.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [November 16, 2018, 3:20am UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902/2 "2018-11-16T03:20:32Z")

</div>

The easiest, and simplest, to publish a custom element plugin is to export a plain class:

```auto
export class MyElementPlugin {
  
}

```

To define view for custom element:

```auto
export class MyElementPlugin {
  static $view = '<template>...</template>'
}

// or with dependencies:
export class MyElementPlugin {
  static $view = {
    template: '<template>...</template>',
    dependencies: () => [ClassBValueConverter, import('./module-a')]
  }
}

```

To declare bindables:

```auto
export class MyElementPlugin {
  static $resource = {
    bindables: [
      'items',
      { name: 'selectedItem', defaultBindingMode: 'twoWay' }
    ]
  }
}

```

Then in your readme, ask the user of your plugin to do:

```auto
import { MyElementPlugin } from 'your-plugin';

...
aurelia.use.globalResources(MyElementPlugin)

```

No that minification will mangle your class name, so defines its resource name explicitly:

```auto
export class MyElementPlugin {
  static $resource = {
    name: 'my-element',
    // if custom attribute:
    // type: 'attribute'
  }
}

```

---

<div class="post-metadata">

**Author:** ![ArchEnemy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/archenemy/32/2445_2.png) [@ArchEnemy](https://discourse.aurelia.io/u/ArchEnemy)\
**Post date:** [November 19, 2018, 2:26am UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902/3 "2018-11-19T02:26:07Z")

</div>

This is a great tutorial. But I have questions… I actually succeeded but I did something completely different.

**Questions for your way:**

- Why static? Why $ dollar sign?
- How come you didn’t use @bindable but used “resource = { bindables:” never seen that before (and why is it that I don’t see this way anywhere)?
- why “globalResources” shouldn’t it be “feature()” or “plugin()” ?

**What I did instead (and please tell me if I did something wrong):**

I may have syntax errors below because I’m not copy pasting.

I made a folder, “MyElementPlugin” then I put in an “index.js”, with:

```auto
export function configure(aurelia) {
    aurelia.globalResources(
      PLATFORM.moduleName('/my-element')
    );
 }

```

my-element.html

```auto
<template>
  <div ref="customElement"></div>
</template>

```

my-element.js has a class with:

```auto
@bindable customElement;

```

Then use needs:

```auto
aurelia.use.feature(PLATFORM.moduleName('MyElementPlugin/index'))

```

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [November 19, 2018, 3:22am UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902/4 "2018-11-19T03:22:38Z")

</div>

> - Why static? Why $ dollar sign?
> - How come you didn’t use @bindable but used “resource = { bindables:” never seen that before (and why is it that I don’t see this way anywhere)?

It’s announced here. [https://aurelia.io/blog/2018/06/24/aurelia-release-notes-june-2018](https://aurelia.io/blog/2018/06/24/aurelia-release-notes-june-2018)  
Traditionally, there’s only one way to register a resource or add a plugin or add a feature: via module path (or module Id string) pointing to the resource/plugin/feature. This doesn’t play well with static code analysis, and part of the reason why it took huge amount of effort to do first webpack plugin. We can refer to this way of adding resource as “dynamic”, as in “not known at build time”:

```js
export class App {
  configureRouter(config) {
    config.map([
      { route: 'home', moduleId: 'pages/home' },
      { route: 'dashboard', moduleId: 'pages/dashboard' }
    ])
  }
}

```

There is no way for tooling to know that `'pages/home'` refers to the file at `'pages/home'` without a plugin or special implementation of bundler like Aurelia-CLI.

Since not all applications need this dynamic capability, it’s desirable to refer to resources via their constructor directly, instead of the module id pointing to where they are, that feature was developed to better support this scenario. Doing it this way helps tooling “see” & “build” dependency graph correctly at build time, aka static, naturally. This enables easier tooling integration, as there is no need for special plugin to teach tooling when a dependency of a module needs to be pulled into the final bundle (like `PLATFORM.moduleName` with webpack).

While developing this feature, I saw that it enables tooling free capability, so it seemed it would be better to have a way to declare bindables or resource configurations easily without decorator, as decorator seemed to be in neverland because of ECMAScript class field proposal. Thus, `$resource` and `$view` was in, `$` is a breaking chance avoidance move, a compromise made to avoid major version bump, without breaking existing app, as `resource` and `view` (or plain field names generally) were pointed out to be too risky.

The final result of this is `aurelia-script` as announced at [https://aurelia.io/blog/2018/11/04/aurelia-2018-q3-report](https://aurelia.io/blog/2018/11/04/aurelia-2018-q3-report), and soon something like following (PR at [WIP feat(router): ability to use classe/module as view model by bigopon · Pull Request #624 · aurelia/router · GitHub](https://github.com/aurelia/router/pull/624) , @davismj and I are working on it) :

```js
export class App {
  configureRouter(config) {
    config.map([
      { route: 'home', viewModel: () => import('pages/home') },
      { route: 'dashboard', viewModel: () => import('pages/dashboard') },
    ]);
  }
}

```

Note that native dynamic import API (or `import('pages/...')`) is naturally understood by probably 100% of tooling, enabling code splitting by default, while still helps with static code analysis.

> - why “globalResources” shouldn’t it be “feature()” or “plugin()” ?

`.feature()`, `.plugin()` when used with a module path, will be resolved to underlying exported `configure` function, which will eventually call `.globalResources()` normally, so if there is no special setup needed, it can be just the direct registration.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [November 19, 2018, 3:37am UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902/5 "2018-11-19T03:37:09Z")

</div>

for:

```auto
<template>
  <div ref="customElement"></div>
</template>

```

you are using `ref` binding, which means its value will be populated by Aurelia. So doing

```auto
@bindable customElement

```

isn’t really needed (the `@bindable`), unless you want to expose the element with `ref="customElement"` to outside. Its value can be accessed in `bind()` and `attached()` lifecycles

---

<div class="post-metadata">

**Author:** ![ArchEnemy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/archenemy/32/2445_2.png) [@ArchEnemy](https://discourse.aurelia.io/u/ArchEnemy)\
**Post date:** [November 20, 2018, 12:50am UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902/6 "2018-11-20T00:50:18Z")

</div>

> viewModel: () =\> import(‘pages/home’)

I’m guessing that means the end of PLATFORM.moduleName for webpack (Aside from backwards compatibility)?

> `configure` function, which will eventually call `.globalResources()`

Doesn’t that mean that I can still use feature()? Feature takes one argument: PLATFORM.moduleName(‘item’)… For readability seems better than calling it “globalResources”? You’re just writing the code for efficiency, since feature() calls globalResources() anyway I assume.

> `ref="customElement"` to outside

The reason I used ref is because I’m building a plugin that requires access to the element. Currently, only “my-element.js” uses the bindable customElement for now.

Basically I have another ES class imported in that needs a variable “myCustomElement” that directly links to the HTML element in the DOM.

`my-element.js`

```auto
@bindable customElement;

attached(){
   generateImageOnDiv();
}

generateImageOnDiv(){
   this.currentClass = new ImportedClass(this.customElement, this.settings);
}

```

And then later from a “parent element” I am accessing “this.currentClass” via bindable in the parent class. To basically, go back in, and change the “this.settings” or other internal fields.

app.js

```auto
export class App {
 @bindable InstanceOfCustom;
  
  constructor(){ } 
  
  InstanceOfCustomChanged(newvalue, oldvalue){
    console.log ("ok, the image is ready on the div... We're ready, we can start manipulating InstanceOfCustom which was just empty", newvalue);
   this.InstanceOfCustom = newvalue;
   this.InstanceOfCustom.settings.push("newsetting", 124);
 }

```

I wasn’t sure how else to expose this.settings to the parent classes aside from `<custom-element settings.bind="passInArray">`

I also thought about using events-aggregator, but currently I’m just using a bindable and `"settingsChanged(newvalue, oldvalue);"`

The reason for all this is because say the new plugin user wants to add more settings and customization. He needs access to the class instance that gets defined INSIDE my-element.js after some seconds.

I think Aurelia Ag-grid plugin is instead using events and binding directly to functions that you are forced to implement. EventInstance.bind=“EventFunctionInYourParentClass” as events or “hooks”.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [November 20, 2018, 1:04am UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902/7 "2018-11-20T01:04:03Z")

</div>

> > `configure` function, which will eventually call `.globalResources()`

> Doesn’t that mean that I can still use feature()? Feature takes one argument: PLATFORM.moduleName(‘item’)… For readability seems better than calling it “globalResources”?

`.feature()` and `.plugin()` both take a config function, then it will be call with `FrameworkConfiguration` instance as its first parameter. Inside that config function, it’s normally called `.globalResources()` on that like this:

```js
export function configure(config: FrameworkConfiguration) {
  config.globalResources(...pluginOrFeatureResources);
}

```

So in the end, it usually boils down to calling `.globalResources()` on `FrameworkConfiguration` instance to config thing. Using plugin / feature enable a delayed call of that, for when you want to do some extra setup.

---

<div class="post-metadata">

**Author:** ![ArchEnemy](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/archenemy/32/2445_2.png) [@ArchEnemy](https://discourse.aurelia.io/u/ArchEnemy)\
**Post date:** [November 22, 2018, 10:52pm UTC](https://discourse.aurelia.io/t/how-do-you-create-aurelia-plugins/1902/8 "2018-11-22T22:52:38Z")

</div>

Is it still okay to use BindableItemChanged(nv, ov){}

To detect when some ES object has been loaded with data from the CHILD element (my-custom-element)?

Or is it better to use events? I am a bit concerned about events, because I may have to do it based on messageType or class, then parse out the id, and it just becomes a very confusing mess of events if they have tons of my “my-custom-elements” on the page.

I don’t want to use a singleton, because there could be multiples. I can’t imagine using DI, because DI would be like the eventaggregator anyway so why not just use events…

Or is there some other creative way to detect that the child element is ready to go and loaded? Perhaps have a different binding “IsLoaded”?

Basically I don’t want the user to use the “@bindable” instance of data, without it being loaded (and attached in the child element). It just seemed weird to use Changed() as the best way to detect this.

Maybe a class gets imported, @inject, then the user has to invoke/implement certain functions inside their “attached()” to get the plugin to work. And that would be part of the plugin install step. Whether loaded or not, the data is queued to be inserted into the child element.

I’m thinking of these things because I want to make plugins for certain things that are advanced UI components and things that require “loading” step or have graphical visual features that take some time to load.
