Skip to content

Commit 06743ca

Browse files
committed
feat(templating): stateful routes
Adds stateful routes so that route configurations can specify a module or a module in a viewport as stateful: true. A stateful module that's loaded in a viewport is never unloaded when navigating away, it's just not shown, and is displayed with the same state whenever a route places it in the same viewport again. Required by aurelia/router/stateful-viewports. Closes aurelia/router#534.
1 parent b43f292 commit 06743ca

File tree

3 files changed

+92
-6
lines changed

3 files changed

+92
-6
lines changed

src/swap-strategies.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,41 @@ export const SwapStrategies = {
2424
return Promise.resolve(viewSlot.removeAll(true)).then(callback);
2525
}
2626
};
27+
28+
export const SwapStrategiesStateful = {
29+
// animate the next viewports in before hiding the current viewports;
30+
before(viewPort, previous, callback) {
31+
return viewPort.hide(false).then(() => callback()).then(() => Promise.all(previous.map((prevViewPort) => {
32+
if (!prevViewPort.stateful) {
33+
return prevViewPort.viewSlot.removeAll(true);
34+
}
35+
else {
36+
return prevViewPort.hide(true);
37+
}
38+
})));
39+
},
40+
41+
// animate the next viewport at the same time the current viewports are removed
42+
with(viewPort, previous, callback) {
43+
return Promise.all(previous.map((prevViewPort) => {
44+
if (!prevViewPort.stateful) {
45+
return prevViewPort.viewSlot.removeAll(true);
46+
}
47+
else {
48+
return prevViewPort.hide(true);
49+
}
50+
}), viewPort.hide(false).then(() => callback()));
51+
},
52+
53+
// animate the next viewport in after the current viewports have been removed
54+
after(viewPort, previous, callback) {
55+
return Promise.all(previous.map((prevViewPort) => {
56+
if (!prevViewPort.stateful) {
57+
return prevViewPort.viewSlot.removeAll(true);
58+
}
59+
else {
60+
return prevViewPort.hide(true);
61+
}
62+
})).then(() => viewPort.hide(false).then(() => callback()));
63+
}
64+
};

src/view-slot.js

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ export class ViewSlot {
5656

5757
if (animatableElement !== null) {
5858
switch (direction) {
59-
case 'enter':
60-
return this.animator.enter(animatableElement);
61-
case 'leave':
62-
return this.animator.leave(animatableElement);
63-
default:
64-
throw new Error('Invalid animation direction: ' + direction);
59+
case 'enter':
60+
return this.animator.enter(animatableElement);
61+
case 'leave':
62+
return this.animator.leave(animatableElement);
63+
default:
64+
throw new Error('Invalid animation direction: ' + direction);
6565
}
6666
}
6767
}
@@ -357,6 +357,40 @@ export class ViewSlot {
357357
return removeAction();
358358
}
359359

360+
/**
361+
* Hides or shows all views in the slot.
362+
* @param hide If the views should be hidden.
363+
* @param skipAnimation Should the removal animation be skipped?
364+
* @return May return a promise if the view removals triggered an animation.
365+
*/
366+
hide(hide_: boolean, skipAnimation?: boolean): void | Promise<any> {
367+
let children = this.children;
368+
let rmPromises = [];
369+
370+
children.forEach(child => {
371+
if (skipAnimation) {
372+
child.hide(hide_);
373+
}
374+
375+
let animation = this.animateView(child, (hide_ ? 'leave' : 'enter'));
376+
if (animation) {
377+
if (hide_) {
378+
rmPromises.push(animation.then(() => child.hide(hide_)));
379+
}
380+
else {
381+
child.hide(hide_);
382+
rmPromises.push(animation);
383+
}
384+
} else {
385+
child.hide(hide_);
386+
}
387+
});
388+
389+
// if (rmPromises.length > 0) {
390+
return Promise.all(rmPromises);
391+
// }
392+
}
393+
360394
/**
361395
* Triggers the attach for the slot and its children.
362396
*/

src/view.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,4 +315,18 @@ export class View {
315315
}
316316
}
317317
}
318+
319+
/**
320+
* Hides or shows view
321+
* @param hide If the view should be hidden
322+
*/
323+
hide(hide_: boolean): void {
324+
let current = this.firstChild;
325+
while (current) {
326+
if (current.style) {
327+
current.style.display = hide_ ? 'none' : '';
328+
}
329+
current = current.nextSibling;
330+
}
331+
}
318332
}

0 commit comments

Comments
 (0)