Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save aicokleinovink/5e0b1999ee4a0d84a44fd4f58bb352d0 to your computer and use it in GitHub Desktop.
Save aicokleinovink/5e0b1999ee4a0d84a44fd4f58bb352d0 to your computer and use it in GitHub Desktop.
Aurelia: composing multiple view models in a side panel
<template>
<div class="side-panel">
<div class="side-panel__header">
<!-- this will pop the last view model from stack -->
<a click.delegate="pop()">Back</a>
Side Panel
<!-- this will close the side panel -->
<a click.delegate="close()">Close</a>
</div>
<div class="side-panel__body">
<!-- this is where the view models will be composed, stack/animate them with CSS -->
<div class="side-panel__stacked-page" repeat.for="viewModel of viewModels">
<compose view-model.bind="viewModel">
</div>
</div>
</div>
</template>
import { autoinject } from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';
@autoinject()
export class SidePanelController {
constructor(private ea: EventAggregator) {
}
public open(viewModel: any): void {
this.ea.publish('side-panel:open', { viewModel });
}
public close(): void {
this.ea.publish('side-panel:close', {});
}
}
<template>
<div class="side-panel">
<div class="side-panel__header">
Side Panel
<!-- this will close the side panel -->
<a click.delegate="close()">Close</a>
</div>
<div class="side-panel__body">
<!-- this is where the view models will be composed -->
<compose view-model.bind="viewModel">
</div>
</div>
</template>
import { autoinject } from 'aurelia-framework';
import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
export interface EventData {
viewModel: any;
}
@autoinject()
export class SidePanel {
public viewModel: any;
public isOpen: boolean;
private subscriptions: Set<Subscription>;
constructor(private ea: EventAggregator) {
this.viewModel = null;
this.isOpen = false;
this.subscriptions = new Set<Subscription>();
}
// Aurelia's attached lifecycle hook
public attached(): void {
const openHandler = (data: EventData) => this.handleOpenEvent(data);
const openSubscription = this.ea.subscribe('side-panel:open', openHandler);
const closeHandler = () => this.handleCloseEvent();
const closeSubscription = this.ea.subscribe('side-panel:close', closeHandler);
this.subscriptions.add(openSubscription);
this.subscriptions.add(closeSubscription);
}
// Aurelia's detached lifecycle hook
public detached(): void {
this.subscriptions.forEach(subscription => subscription.dispose());
}
private handleOpenEvent({ viewModel }: EventData): void {
this.viewModel = viewModel;
this.isOpen = true;
}
private handeCloseEvent(): void {
this.viewModel = null;
this.isOpen = false;
}
}
<template>
<button click.delegate="buttonClicked()">Open Side Panel</button>
</template>
import { autoinject } from 'aurelia-framework';
import { SidePanelController } from 'services/side-panel.controller';
import { ViewModelOne } from './view-model-one';
import { ViewModelTwo } from './view-model-two';
@autoinject()
export class SomePage {
constructor(private sidePanelController: SidePanelController) {
}
public buttonClicked(): void {
const viewModel = new ViewModelOne(); // this could also be ViewModelTwo
this.sidePanelController.open(viewModel);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment