# Aurelia Cheat Sheet ## [Configuration and Startup](aurelia-doc://section/1/version/1.0.0) ### Bootstrapping Older Browsers ```html ``` > Warning: Promises in Edge > Currently, the Edge browser has a serious performance problem with its Promise implementation. This deficiency can greatly increase startup time of your app. If you are targeting the Edge browser, it is highly recommended that you use the [bluebird promise](http://bluebirdjs.com/docs/getting-started.html) library to replace Edge's native implementation. You can do this by simply referencing the library prior to loading system.js. ### Standard Startup Configuration ```javascript export function configure(aurelia) { aurelia.use .standardConfiguration() .developmentLogging(); aurelia.start().then(() => aurelia.setRoot()); } ``` ```typescript import {Aurelia} from 'aurelia-framework'; export function configure(aurelia: Aurelia): void { aurelia.use .standardConfiguration() .developmentLogging(); aurelia.start().then(() => aurelia.setRoot()); } ``` ### Explicit Startup Configuration ```javascript import {LogManager} from 'aurelia-framework'; import {ConsoleAppender} from 'aurelia-logging-console'; LogManager.addAppender(new ConsoleAppender()); LogManager.setLevel(LogManager.logLevel.debug); export function configure(aurelia) { aurelia.use .defaultBindingLanguage() .defaultResources() .history() .router() .eventAggregator(); aurelia.start().then(() => aurelia.setRoot('app', document.body)); } ``` --- ```typescript import {LogManager, Aurelia} from 'aurelia-framework'; import {ConsoleAppender} from 'aurelia-logging-console'; LogManager.addAppender(new ConsoleAppender()); LogManager.setLevel(LogManager.logLevel.debug); export function configure(aurelia: Aurelia): void { aurelia.use .defaultBindingLanguage() .defaultResources() .history() .router() .eventAggregator(); aurelia.start().then(() => aurelia.setRoot('app', document.body)); } ``` ### Configuring A Feature ```jaavascript export function configure(aurelia) { aurelia.use .standardConfiguration() .developmentLogging() .feature('feature-name', featureConfiguration); aurelia.start().then(() => aurelia.setRoot()); } ``` --- ```typescript import {Aurelia} from 'aurelia-framework'; export function configure(aurelia: Aurelia): void { aurelia.use .standardConfiguration() .developmentLogging() .feature('feature-name', featureConfiguration); aurelia.start().then(() => aurelia.setRoot()); } ``` ### Installing a Plugin ```javascript export function configure(aurelia) { aurelia.use .standardConfiguration() .developmentLogging() .plugin('plugin-name', pluginConfiguration); aurelia.start().then(() => aurelia.setRoot()); } ``` --- ```typescript import {Aurelia} from 'aurelia-framework'; export function configure(aurelia: Aurelia): void { aurelia.use .standardConfiguration() .developmentLogging() .plugin('plugin-name', pluginConfiguration); aurelia.start().then(() => aurelia.setRoot()); } ``` ## [Creating Components](aurelia-doc://section/2/version/1.0.0) UI components consist of two parts: a view-model and a view. Simply create each part in its own file. Use the same file name but different file extensions for the two parts. For example: _hello${context.language.fileExtension}_ and _hello.html_. ### Explicit Configuration ###### ES 2015 ```javascript import {useView, decorators} from 'aurelia-framework'; export let Hello = decorators(useView('./hello.html')).on(class { ... }); ``` ###### ES 2016 ```javascript import {useView} from 'aurelia-framework'; @useView('./hello.html') export class Hello { ... } ``` ###### Typescript ```typescript import {useView} from 'aurelia-framework'; @useView('./hello.html') export class Hello { ... } ``` #### The Component Lifecycle Components have a well-defined lifecycle: 1. `constructor()` - The view-model's constructor is called first. 2. `created(owningView: View, myView: View)` - If the view-model implements the `created` callback it is invoked next. At this point in time, the view has also been created and both the view-model and the view are connected to their controller. The created callback will receive the instance of the "owningView". This is the view that the component is declared inside of. If the component itself has a view, this will be passed second. 3. `bind(bindingContext: Object, overrideContext: Object)` - Databinding is then activated on the view and view-model. If the view-model has a `bind` callback, it will be invoked at this time. The "binding context" to which the component is being bound will be passed first. An "override context" will be passed second. The override context contains information used to traverse the parent hierarchy and can also be used to add any contextual properties that the component wants to add. It should be noted that when the view-model has implemented the `bind` callback, the databinding framework will not invoke the changed handlers for the view-model's bindable properties until the "next" time those properties are updated. If you need to perform specific post-processing on your bindable properties, when implementing the `bind` callback, you should do so manually within the callback itself. 4. `attached()` - Next, the component is attached to the DOM (in document). If the view-model has an `attached` callback, it will be invoked at this time. 5. `detached()` - At some point in the future, the component may be removed from the DOM. If/When this happens, and if the view-model has a `detached` callback, this is when it will be invoked. 6. `unbind()` - After a component is detached, it's usually unbound. If your view-model has the `unbind` callback, it will be invoked during this process. ## [Dependency Injection](aurelia-doc://section/3/version/1.0.0) import {inject} from 'aurelia-framework'; import {Dep1} from 'dep1'; import {Dep2} from 'dep2'; @inject(Dep1, Dep2) export class CustomerDetail { constructor(dep1, dep2) { this.dep1 = dep1; this.dep2 = dep2; } } import {Dep1} from 'dep1'; import {Dep2} from 'dep2'; export class CustomerDetail { static inject() { return [Dep1, Dep2]; } constructor(dep1, dep2) { this.dep1 = dep1; this.dep2 = dep2; } } import {autoinject} from 'aurelia-framework'; import {Dep1} from 'dep1'; import {Dep2} from 'dep2'; @autoinject export class CustomerDetail { constructor(private dep1: Dep1, private dep2: Dep2){ } } import {Lazy, inject} from 'aurelia-framework'; import {HttpClient} from 'aurelia-fetch-client'; @inject(Lazy.of(HttpClient)) export class CustomerDetail { constructor(getHTTP){ this.getHTTP = getHTTP; } } import {Lazy} from 'aurelia-framework'; import {HttpClient} from 'aurelia-fetch-client'; export class CustomerDetail { static inject() { return [Lazy.of(HttpClient)]; } constructor(getHTTP){ this.getHTTP = getHTTP; } } import {Lazy, inject} from 'aurelia-framework'; import {HttpClient} from 'aurelia-fetch-client'; @inject(Lazy.of(HttpClient)) export class CustomerDetail { constructor(private getHTTP: () => HttpClient){ } } #### Available Resolvers * `Lazy` - Injects a function for lazily evaluating the dependency. * ex. `Lazy.of(HttpClient)` * `All` - Injects an array of all services registered with the provided key. * ex. `All.of(Plugin)` * `Optional` - Injects an instance of a class only if it already exists in the container; null otherwise. * ex. `Optional.of(LoggedInUser)` * `Parent` - Skips starting dependency resolution from the current container and instead begins the lookup process on the parent container. * ex. `Parent.of(MyCustomElement)` * `Factory` - Used to allow injecting dependencies, but also passing data to the constructor. * ex. `Factory.of(CustomClass)` * `NewInstance` - Used to inject a new instance of a dependency, without regard for existing instances in the container. * ex. `NewInstance.of(CustomClass).as(Another)` import {transient, inject} from 'aurelia-framework'; import {HttpClient} from 'aurelia-fetch-client'; @transient() @inject(HttpClient) export class CustomerDetail { constructor(http) { this.http = http; } } import {transient, inject} from 'aurelia-framework'; import {HttpClient} from 'aurelia-fetch-client'; export let CustomDetail = decorators( transient() inject(HttpClient) ).on(class { constructor(http) { this.http = http; } }); import {transient, autoinject} from 'aurelia-framework'; import {HttpClient} from 'aurelia-fetch-client'; @transient() @autoinject export class CustomerDetail { constructor(private http: HttpClient) { } } ## [Templating Basics](aurelia-doc://section/4/version/1.0.0) > Info: Invalid Table Structure When Dynamically Creating Tables > When the browser loads in the template it very helpfully validates the structure of the HTML, notices that you have an invalid tag inside your table definition, and very unhelpfully removes it for you before Aurelia even has a chance to examine your template. Use of the `as-element` attribute ensures we have a valid HTML table structure at load time, yet we tell Aurelia to treat its contents as though it were a different tag.