diff --git a/config.js b/config.js
index 3e905b6..3c273f2 100644
--- a/config.js
+++ b/config.js
@@ -15,89 +15,198 @@ System.config({
},
map: {
- "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.1.4",
- "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2",
- "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5",
- "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1",
- "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1",
- "aurelia-polyfills": "npm:aurelia-polyfills@1.0.0-beta.1.0.6",
- "aurelia-router": "npm:aurelia-router@1.0.0-beta.1.1.0",
- "aurelia-templating": "npm:aurelia-templating@1.0.0-beta.1.1.2",
- "babel": "npm:babel-core@5.8.35",
- "babel-runtime": "npm:babel-runtime@5.8.35",
- "core-js": "npm:core-js@2.0.3",
+ "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3",
+ "aurelia-event-aggregator": "npm:aurelia-event-aggregator@1.0.0-beta.1.2.1",
+ "aurelia-framework": "npm:aurelia-framework@1.0.0-beta.1.2.5",
+ "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.2.1",
+ "aurelia-history-browser": "npm:aurelia-history-browser@1.0.0-beta.1.2.1",
+ "aurelia-loader-default": "npm:aurelia-loader-default@1.0.0-beta.1.2.2",
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-logging-console": "npm:aurelia-logging-console@1.0.0-beta.1.2.2",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "github:aurelia/pal@1.0.0-beta.1.2.2",
+ "aurelia-pal-browser": "github:aurelia/pal-browser@1.0.0-beta.2.0.1",
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2",
+ "aurelia-polyfills": "npm:aurelia-polyfills@1.0.0-beta.1.1.6",
+ "aurelia-router": "npm:aurelia-router@1.0.0-beta.1.2.4",
+ "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1",
+ "aurelia-templating-binding": "npm:aurelia-templating-binding@1.0.0-beta.1.2.4",
+ "aurelia-templating-resources": "npm:aurelia-templating-resources@1.0.0-beta.1.2.6",
+ "aurelia-templating-router": "npm:aurelia-templating-router@1.0.0-beta.1.2.1",
+ "aurelia-testing": "npm:aurelia-testing@0.2.2",
+ "babel": "npm:babel-core@5.8.38",
+ "babel-runtime": "npm:babel-runtime@5.8.38",
+ "core-js": "npm:core-js@2.4.0",
+ "github:aurelia/pal-browser@1.0.0-beta.2.0.1": {
+ "aurelia-pal": "github:aurelia/pal@1.0.0-beta.1.2.2"
+ },
+ "github:aurelia/templating@1.0.0-beta.2.0.1": {
+ "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6",
+ "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3",
+ "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0",
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2",
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2",
+ "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1"
+ },
"github:jspm/nodelibs-assert@0.1.0": {
- "assert": "npm:assert@1.3.0"
+ "assert": "npm:assert@1.4.1"
+ },
+ "github:jspm/nodelibs-buffer@0.1.0": {
+ "buffer": "npm:buffer@3.6.0"
},
"github:jspm/nodelibs-path@0.1.0": {
"path-browserify": "npm:path-browserify@0.0.0"
},
"github:jspm/nodelibs-process@0.1.2": {
- "process": "npm:process@0.11.2"
+ "process": "npm:process@0.11.3"
},
"github:jspm/nodelibs-util@0.1.0": {
"util": "npm:util@0.10.3"
},
- "npm:assert@1.3.0": {
+ "npm:assert@1.4.1": {
+ "assert": "github:jspm/nodelibs-assert@0.1.0",
+ "buffer": "github:jspm/nodelibs-buffer@0.1.0",
+ "process": "github:jspm/nodelibs-process@0.1.2",
"util": "npm:util@0.10.3"
},
- "npm:aurelia-binding@1.0.0-beta.1.2.1": {
- "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5",
- "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1",
- "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.1.1"
- },
- "npm:aurelia-dependency-injection@1.0.0-beta.1.1.4": {
- "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2",
- "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5",
- "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1"
- },
- "npm:aurelia-event-aggregator@1.0.0-beta.1.1.0": {
- "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2"
- },
- "npm:aurelia-loader@1.0.0-beta.1.1.1": {
- "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5",
- "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1"
- },
- "npm:aurelia-metadata@1.0.0-beta.1.1.5": {
- "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1"
- },
- "npm:aurelia-polyfills@1.0.0-beta.1.0.6": {
- "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1"
- },
- "npm:aurelia-route-recognizer@1.0.0-beta.1.1.0": {
- "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1",
- "core-js": "npm:core-js@2.0.3"
- },
- "npm:aurelia-router@1.0.0-beta.1.1.0": {
- "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.1.4",
- "aurelia-event-aggregator": "npm:aurelia-event-aggregator@1.0.0-beta.1.1.0",
- "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.1.1",
- "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2",
- "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1",
- "aurelia-route-recognizer": "npm:aurelia-route-recognizer@1.0.0-beta.1.1.0",
- "core-js": "npm:core-js@2.0.3"
- },
- "npm:aurelia-task-queue@1.0.0-beta.1.1.1": {
- "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1"
- },
- "npm:aurelia-templating@1.0.0-beta.1.1.2": {
- "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.2.1",
- "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.1.4",
- "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.1.1",
- "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2",
- "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5",
- "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1",
- "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1",
- "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.1.1"
- },
- "npm:babel-runtime@5.8.35": {
+ "npm:aurelia-binding@1.0.0-beta.1.3.6": {
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2",
+ "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1"
+ },
+ "npm:aurelia-bootstrapper@1.0.0-beta.1.2.1": {
+ "aurelia-event-aggregator": "npm:aurelia-event-aggregator@1.0.0-beta.1.2.1",
+ "aurelia-framework": "npm:aurelia-framework@1.0.0-beta.1.2.5",
+ "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.2.1",
+ "aurelia-history-browser": "npm:aurelia-history-browser@1.0.0-beta.1.2.1",
+ "aurelia-loader-default": "npm:aurelia-loader-default@1.0.0-beta.1.2.2",
+ "aurelia-logging-console": "npm:aurelia-logging-console@1.0.0-beta.1.2.2",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2",
+ "aurelia-pal-browser": "npm:aurelia-pal-browser@1.0.0-beta.2.0.1",
+ "aurelia-polyfills": "npm:aurelia-polyfills@1.0.0-beta.1.1.6",
+ "aurelia-router": "npm:aurelia-router@1.0.0-beta.1.2.4",
+ "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1",
+ "aurelia-templating-binding": "npm:aurelia-templating-binding@1.0.0-beta.1.2.4",
+ "aurelia-templating-resources": "npm:aurelia-templating-resources@1.0.0-beta.1.2.6",
+ "aurelia-templating-router": "npm:aurelia-templating-router@1.0.0-beta.1.2.1"
+ },
+ "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3": {
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-event-aggregator@1.0.0-beta.1.2.1": {
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1"
+ },
+ "npm:aurelia-framework@1.0.0-beta.1.2.5": {
+ "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6",
+ "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3",
+ "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0",
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2",
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2",
+ "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1",
+ "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1"
+ },
+ "npm:aurelia-history-browser@1.0.0-beta.1.2.1": {
+ "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.2.1",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-loader-default@1.0.0-beta.1.2.2": {
+ "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-loader@1.0.0-beta.1.2.0": {
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-logging-console@1.0.0-beta.1.2.2": {
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1"
+ },
+ "npm:aurelia-metadata@1.0.0-beta.1.2.1": {
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-pal-browser@1.0.0-beta.2.0.1": {
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-polyfills@1.0.0-beta.1.1.6": {
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-route-recognizer@1.0.0-beta.1.2.1": {
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-router@1.0.0-beta.1.2.4": {
+ "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3",
+ "aurelia-event-aggregator": "npm:aurelia-event-aggregator@1.0.0-beta.1.2.1",
+ "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.2.1",
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2",
+ "aurelia-route-recognizer": "npm:aurelia-route-recognizer@1.0.0-beta.1.2.1"
+ },
+ "npm:aurelia-task-queue@1.0.0-beta.1.2.1": {
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2"
+ },
+ "npm:aurelia-templating-binding@1.0.0-beta.1.2.4": {
+ "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6",
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1"
+ },
+ "npm:aurelia-templating-resources@1.0.0-beta.1.2.6": {
+ "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6",
+ "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3",
+ "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0",
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2",
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2",
+ "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1",
+ "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1"
+ },
+ "npm:aurelia-templating-router@1.0.0-beta.1.2.1": {
+ "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3",
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2",
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2",
+ "aurelia-router": "npm:aurelia-router@1.0.0-beta.1.2.4",
+ "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1"
+ },
+ "github:aurelia/templating@1.0.0-beta.2.0.1": {
+ "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6",
+ "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3",
+ "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0",
+ "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1",
+ "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1",
+ "aurelia-pal": "github:aurelia/pal@1.0.0-beta.1.2.2",
+ "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2",
+ "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1"
+ },
+ "npm:aurelia-testing@0.2.2": {
+ "aurelia-bootstrapper": "npm:aurelia-bootstrapper@1.0.0-beta.1.2.1",
+ "aurelia-framework": "npm:aurelia-framework@1.0.0-beta.1.2.5",
+ "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1"
+ },
+ "npm:babel-runtime@5.8.38": {
+ "process": "github:jspm/nodelibs-process@0.1.2"
+ },
+ "npm:buffer@3.6.0": {
+ "base64-js": "npm:base64-js@0.0.8",
+ "child_process": "github:jspm/nodelibs-child_process@0.1.0",
+ "fs": "github:jspm/nodelibs-fs@0.1.2",
+ "ieee754": "npm:ieee754@1.1.6",
+ "isarray": "npm:isarray@1.0.0",
"process": "github:jspm/nodelibs-process@0.1.2"
},
- "npm:core-js@2.0.3": {
+ "npm:core-js@2.4.0": {
"fs": "github:jspm/nodelibs-fs@0.1.2",
"path": "github:jspm/nodelibs-path@0.1.0",
"process": "github:jspm/nodelibs-process@0.1.2",
- "systemjs-json": "github:systemjs/plugin-json@0.1.0"
+ "systemjs-json": "github:systemjs/plugin-json@0.1.2"
},
"npm:inherits@2.0.1": {
"util": "github:jspm/nodelibs-util@0.1.0"
@@ -105,7 +214,7 @@ System.config({
"npm:path-browserify@0.0.0": {
"process": "github:jspm/nodelibs-process@0.1.2"
},
- "npm:process@0.11.2": {
+ "npm:process@0.11.3": {
"assert": "github:jspm/nodelibs-assert@0.1.0"
},
"npm:util@0.10.3": {
diff --git a/karma.conf.js b/karma.conf.js
index db3d86d..d87b30a 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -15,12 +15,12 @@ module.exports = function(config) {
jspm: {
// Edit this to your needs
loadFiles: ['test/setup.js', 'test/**/*.js'],
- serveFiles: ['src/**/*.js'],
+ serveFiles: ['src/**/*.js']
},
// list of files / patterns to load in the browser
- files: [],
+ files: ['test/**/*.html'],
// list of files to exclude
diff --git a/src/router-view.js b/src/router-view.js
index dca4aeb..c72b0b5 100644
--- a/src/router-view.js
+++ b/src/router-view.js
@@ -1,5 +1,5 @@
import {Container, inject} from 'aurelia-dependency-injection';
-import {ViewSlot, ViewLocator, customElement, noView, BehaviorInstruction, bindable, CompositionTransaction} from 'aurelia-templating';
+import {ViewSlot, ViewLocator, customElement, noView, BehaviorInstruction, bindable, CompositionTransaction, CompositionEngine, ShadowDOM} from 'aurelia-templating';
import {Router} from 'aurelia-router';
import {Origin} from 'aurelia-metadata';
import {DOM} from 'aurelia-pal';
@@ -37,17 +37,21 @@ const swapStrategies = new SwapStrategies();
@customElement('router-view')
@noView
-@inject(DOM.Element, Container, ViewSlot, Router, ViewLocator, CompositionTransaction)
+@inject(DOM.Element, Container, ViewSlot, Router, ViewLocator, CompositionTransaction, CompositionEngine)
export class RouterView {
@bindable swapOrder;
+ @bindable layoutView;
+ @bindable layoutViewModel;
+ @bindable layoutModel;
- constructor(element, container, viewSlot, router, viewLocator, compositionTransaction) {
+ constructor(element, container, viewSlot, router, viewLocator, compositionTransaction, compositionEngine) {
this.element = element;
this.container = container;
this.viewSlot = viewSlot;
this.router = router;
this.viewLocator = viewLocator;
this.compositionTransaction = compositionTransaction;
+ this.compositionEngine = compositionEngine;
this.router.registerViewPort(this, this.element.getAttribute('name'));
if (!('initialComposition' in compositionTransaction)) {
@@ -71,53 +75,83 @@ export class RouterView {
let viewModel = component.viewModel;
let viewModelResource = component.viewModelResource;
let metadata = viewModelResource.metadata;
+ let config = component.router.currentInstruction.config;
+ let viewPort = config.viewPorts ? config.viewPorts[viewPortInstruction.name] : {};
+
+ // layoutInstruction is our layout viewModel
+ let layoutInstruction = {
+ viewModel: viewPort.layoutViewModel || config.layoutViewModel || this.layoutViewModel,
+ view: viewPort.layoutView || config.layoutView || this.layoutView,
+ model: viewPort.layoutModel || config.layoutModel || this.layoutModel,
+ router: viewPortInstruction.component.router,
+ childContainer: childContainer,
+ viewSlot: this.viewSlot
+ };
- let viewStrategy = this.viewLocator.getViewStrategy(component.view || viewModel);
- if (viewStrategy) {
- viewStrategy.makeRelativeTo(Origin.get(component.router.container.viewModel.constructor).moduleId);
- }
+ return Promise.resolve(this.composeLayout(layoutInstruction))
+ .then(layoutView => {
+ let viewStrategy = this.viewLocator.getViewStrategy(component.view || viewModel);
- return metadata.load(childContainer, viewModelResource.value, null, viewStrategy, true).then(viewFactory => {
- if (!this.compositionTransactionNotifier) {
- this.compositionTransactionOwnershipToken = this.compositionTransaction.tryCapture();
+ if (viewStrategy) {
+ viewStrategy.makeRelativeTo(Origin.get(component.router.container.viewModel.constructor).moduleId);
}
- viewPortInstruction.controller = metadata.create(childContainer,
- BehaviorInstruction.dynamic(
- this.element,
- viewModel,
- viewFactory
- )
- );
+ return metadata.load(childContainer, viewModelResource.value, null, viewStrategy, true)
+ .then(viewFactory => {
+ if (!this.compositionTransactionNotifier) {
+ this.compositionTransactionOwnershipToken = this.compositionTransaction.tryCapture();
+ }
- if (waitToSwap) {
- return;
- }
+ viewPortInstruction.layout = layoutView ? layoutView.view || layoutView : undefined;
+
+ viewPortInstruction.controller = metadata.create(childContainer,
+ BehaviorInstruction.dynamic(
+ this.element,
+ viewModel,
+ viewFactory
+ )
+ );
- this.swap(viewPortInstruction);
+ if (waitToSwap) {
+ return;
+ }
+
+ this.swap(viewPortInstruction);
+ });
});
}
+ composeLayout(instruction) {
+ if (instruction.viewModel || instruction.view) {
+ return this.compositionEngine.compose(instruction);
+ }
+ }
+
swap(viewPortInstruction) {
let work = () => {
let previousView = this.view;
- let viewSlot = this.viewSlot;
let swapStrategy;
+ let layout = viewPortInstruction.layout;
+ let viewSlot = layout ? new ViewSlot(layout.firstChild, false) : this.viewSlot;
+
+ if (layout) {
+ viewSlot.attached();
+ }
swapStrategy = this.swapOrder in swapStrategies
? swapStrategies[this.swapOrder]
: swapStrategies.after;
swapStrategy(viewSlot, previousView, () => {
- return Promise.resolve(viewSlot.add(viewPortInstruction.controller.view)).then(() => {
- if (this.compositionTransactionNotifier) {
- this.compositionTransactionNotifier.done();
- this.compositionTransactionNotifier = null;
- }
- });
+ if (layout) {
+ ShadowDOM.distributeView(viewPortInstruction.controller.view, layout.slots, viewSlot);
+ this._notify();
+ } else {
+ return Promise.resolve(viewSlot.add(viewPortInstruction.controller.view)).then(() => { this._notify(); });
+ }
+
+ this.view = viewPortInstruction.controller.view;
});
-
- this.view = viewPortInstruction.controller.view;
};
viewPortInstruction.controller.automate(this.overrideContext, this.owningView);
@@ -131,4 +165,11 @@ export class RouterView {
work();
}
+
+ _notify() {
+ if (this.compositionTransactionNotifier) {
+ this.compositionTransactionNotifier.done();
+ this.compositionTransactionNotifier = null;
+ }
+ }
}
diff --git a/test/layout-default-slot-alt.html b/test/layout-default-slot-alt.html
new file mode 100644
index 0000000..5a126e5
--- /dev/null
+++ b/test/layout-default-slot-alt.html
@@ -0,0 +1,4 @@
+
+ alt layout
+
+
diff --git a/test/layout-default-slot.html b/test/layout-default-slot.html
new file mode 100644
index 0000000..c7fa10e
--- /dev/null
+++ b/test/layout-default-slot.html
@@ -0,0 +1,4 @@
+
+ default layout
+
+
diff --git a/test/layout-default-slot.js b/test/layout-default-slot.js
new file mode 100644
index 0000000..a7ea7bb
--- /dev/null
+++ b/test/layout-default-slot.js
@@ -0,0 +1,9 @@
+import {testConstants} from '../test/test-constants';
+
+export class LayoutDefaultSlot {
+ constants = testConstants;
+
+ activate(value) {
+ this.value = value;
+ }
+}
diff --git a/test/layout-named-slots.html b/test/layout-named-slots.html
new file mode 100644
index 0000000..da730d4
--- /dev/null
+++ b/test/layout-named-slots.html
@@ -0,0 +1,5 @@
+
+ named slots layout
+
+
+
diff --git a/test/module-default-slot.html b/test/module-default-slot.html
new file mode 100644
index 0000000..50397cb
--- /dev/null
+++ b/test/module-default-slot.html
@@ -0,0 +1,3 @@
+
+ ${constants.content}
+
diff --git a/test/module-default-slot.js b/test/module-default-slot.js
new file mode 100644
index 0000000..68cdfc6
--- /dev/null
+++ b/test/module-default-slot.js
@@ -0,0 +1,5 @@
+import {testConstants} from 'test/test-constants';
+
+export class ModuleDefaultSlot {
+ constants = testConstants;
+}
diff --git a/test/module-named-slots.html b/test/module-named-slots.html
new file mode 100644
index 0000000..674867d
--- /dev/null
+++ b/test/module-named-slots.html
@@ -0,0 +1,4 @@
+
+ ${constants.content}
+ ${constants.content}
+
diff --git a/test/module-named-slots.js b/test/module-named-slots.js
new file mode 100644
index 0000000..f117537
--- /dev/null
+++ b/test/module-named-slots.js
@@ -0,0 +1,5 @@
+import {testConstants} from 'test/test-constants';
+
+export class ModuleNamedSlots {
+ constants = testConstants;
+}
diff --git a/test/router-view.spec.js b/test/router-view.spec.js
index 0403a5b..72c24a2 100644
--- a/test/router-view.spec.js
+++ b/test/router-view.spec.js
@@ -1,5 +1,174 @@
-describe('router-view', () => {
- it('should exist', () => {
- expect(true).toBe(true);
+import {StageComponent} from 'aurelia-testing';
+import {RouteLoader, AppRouter, Router} from 'aurelia-router';
+import {TemplatingRouteLoader} from 'src/route-loader';
+import {testConstants} from 'test/test-constants';
+
+describe('router-view', () => {
+ let component;
+
+ beforeEach(done => {
+ done();
+ });
+
+ afterEach(done => {
+ component.viewModel.router.navigate('default').then(() => {
+ component.dispose();
+ done();
+ });
+ });
+
+ it('has a router instance', done => {
+ component = withDefaultViewport({ moduleId: 'test/module-default-slot' });
+ component.create()
+ .then(() => {
+ expect(component.viewModel.router).not.toBe(undefined);
+ })
+ .then(done);
+ });
+
+ it('loads a non-layout based view', done => {
+ component = withDefaultViewport({ moduleId: 'test/module-default-slot' });
+ component.create()
+ .then(() => {
+ return component.viewModel.router.navigate('route');
+ })
+ .then(() => {
+ expect(component.viewModel.element.innerText).toContain(testConstants.content);
+ })
+ .then(done);
+ });
+
+ it('loads a view-only layout', done => {
+ component = withDefaultViewport({ moduleId: 'test/module-default-slot', layoutView: 'test/layout-default-slot.html' });
+ component.create()
+ .then(() => {
+ return component.viewModel.router.navigate('route');
+ })
+ .then(() => {
+ expect(component.viewModel.element.innerText).toContain(testConstants.content);
+ expect(component.viewModel.element.innerText).toContain(testConstants.defaultLayout);
+ })
+ .then(done);
+ });
+
+ it('loads a module based layout', done => {
+ component = withDefaultViewport({ moduleId: 'test/module-default-slot', layoutViewModel: 'test/layout-default-slot' });
+ component.create()
+ .then(() => {
+ return component.viewModel.router.navigate('route');
+ })
+ .then(() => {
+ expect(component.viewModel.element.innerText).toContain(testConstants.content);
+ expect(component.viewModel.element.innerText).toContain(testConstants.defaultLayout);
+ expect(component.viewModel.viewSlot.children[0].controller.viewModel).not.toBe(undefined);
+ })
+ .then(done);
+ });
+
+ it('loads a module based layout with a specific view', done => {
+ component = withDefaultViewport({ moduleId: 'test/module-default-slot', layoutView: 'test/layout-default-slot-alt.html', layoutViewModel: 'test/layout-default-slot' });
+ component.create()
+ .then(() => {
+ return component.viewModel.router.navigate('route');
+ })
+ .then(() => {
+ expect(component.viewModel.element.innerText).toContain(testConstants.content);
+ expect(component.viewModel.element.innerText).toContain(testConstants.altLayout);
+ expect(component.viewModel.viewSlot.children[0].controller.viewModel).not.toBe(undefined);
+ })
+ .then(done);
+ });
+
+ it('loads a layout with multiple slots', done => {
+ component = withDefaultViewport({ moduleId: 'test/module-named-slots', layoutView: 'test/layout-named-slots.html' });
+ component.create()
+ .then(() => {
+ return component.viewModel.router.navigate('route');
+ })
+ .then(() => {
+ expect(component.viewModel.element.innerText).toContain(testConstants.content + '\n' + testConstants.content);
+ expect(component.viewModel.element.innerText).toContain(testConstants.namedSlotsLayout);
+ })
+ .then(done);
+ });
+
+ it('loads layouts for a named viewport', done => {
+ component = withNamedViewport({
+ viewPorts: {
+ viewport1: { moduleId: 'test/module-default-slot', layoutView: 'test/layout-default-slot.html' }
+ }
+ });
+ component.create()
+ .then(() => {
+ return component.viewModel.router.navigate('route');
+ })
+ .then(() => {
+ expect(component.viewModel.element.innerText).toContain(testConstants.content);
+ expect(component.viewModel.element.innerText).toContain(testConstants.defaultLayout);
+ })
+ .then(done);
+ });
+
+ it('activates the layout viewmodel with a model value', done => {
+ component = withDefaultViewport({ moduleId: 'test/module-default-slot', layoutViewModel: 'test/layout-default-slot', layoutModel: 1 });
+ component.create()
+ .then(() => {
+ return component.viewModel.router.navigate('route');
+ })
+ .then(() => {
+ expect(component.viewModel.viewSlot.children[0].controller.viewModel.value).toBe(1);
+ })
+ .then(done);
});
});
+
+function withDefaultViewport(routeConfig) {
+ let component = StageComponent
+ .withResources('src/router-view')
+ .inView('');
+ bootstrap(component, { route: ['', 'default'], moduleId: 'test/module-default-slot', activationStrategy: 'replace'}, routeConfig);
+ return component;
+}
+
+function withNamedViewport(routeConfig) {
+ let component = StageComponent
+ .withResources('src/router-view')
+ .inView('');
+ bootstrap(component,
+ {
+ route: ['', 'default'],
+ viewPorts: {
+ viewport1: { moduleId: 'test/module-default-slot' }
+ },
+ activationStrategy: 'replace'
+ },
+ routeConfig);
+ return component;
+}
+
+function bootstrap(component, defaultRoute, routeConfig) {
+ component.bootstrap(aurelia => {
+ aurelia.use.defaultBindingLanguage()
+ .defaultResources()
+ .history();
+// .developmentLogging();
+
+ aurelia.use.singleton(RouteLoader, TemplatingRouteLoader)
+ .singleton(Router, AppRouter)
+ .globalResources('src/router-view', 'src/route-href');
+
+ if (routeConfig) {
+ routeConfig.activationStrategy = 'replace';
+ routeConfig.route = 'route';
+ routeConfig = [defaultRoute, routeConfig];
+ } else {
+ routeConfig = [defaultRoute];
+ }
+
+ aurelia.use.container.viewModel = {
+ configureRouter: (config, router) => {
+ config.map(routeConfig);
+ }
+ };
+ });
+}
diff --git a/test/setup.js b/test/setup.js
index 30fb7eb..a2498cc 100644
--- a/test/setup.js
+++ b/test/setup.js
@@ -1 +1,3 @@
import 'aurelia-polyfills';
+import {initialize} from 'aurelia-pal-browser';
+initialize();
diff --git a/test/test-constants.js b/test/test-constants.js
new file mode 100644
index 0000000..bc16d29
--- /dev/null
+++ b/test/test-constants.js
@@ -0,0 +1,6 @@
+export const testConstants = {
+ content: 'test content',
+ defaultLayout: 'default layout',
+ altLayout: 'alt layout',
+ namedSlotsLayout: 'named slots layout'
+};
diff --git a/test/test-router-view.html b/test/test-router-view.html
new file mode 100644
index 0000000..3f94534
--- /dev/null
+++ b/test/test-router-view.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/test/test-router-view.js b/test/test-router-view.js
new file mode 100644
index 0000000..ddd38f3
--- /dev/null
+++ b/test/test-router-view.js
@@ -0,0 +1,2 @@
+export class TestRouterView {
+}