Skip to content

Commit

Permalink
[FEATURE RFC 631] Add a refresh method to the router service
Browse files Browse the repository at this point in the history
This adds the refresh method to the RouterService as described in RFC 631.

RFC PR: emberjs/rfcs#631
  • Loading branch information
Windvis committed Mar 19, 2021
1 parent 22bfcfd commit bdc223c
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
27 changes: 27 additions & 0 deletions packages/@ember/-internals/routing/lib/services/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { assign } from '@ember/polyfills';
import Service from '@ember/service';
import { consumeTag, tagFor } from '@glimmer/validator';
import EmberRouter, { QueryParam } from '../system/router';
import Route from '../system/route';
import { extractRouteArgs, resemblesURL, shallowEqual } from '../utils';

const ROUTER = symbol('ROUTER') as string;
Expand Down Expand Up @@ -393,6 +394,32 @@ export default class RouterService extends Service {
return this._router._routerMicrolib.recognizeAndLoad(internalURL);
}

/**
* Refreshes all currently active routes, doing a full transition.
* If a routeName is provided and refers to a currently active route,
* it will refresh only that route and its descendents.
* Returns a promise that will be resolved once the refresh is complete.
* All resetController, beforeModel, model, afterModel, redirect, and setupController
* hooks will be called again. You will get new data from the model hook.
*
* @method refresh
* @param {String} [routeName] the route to refresh (along with all child routes)
* @return Transition
* @public
*/
refresh(routeName?: string) {
if (!routeName) {
return this._router._routerMicrolib.refresh();
}

assert(`The route "${routeName}" was not found`, this._router.hasRoute(routeName));
assert(`The route "${routeName}" is currently not active`, this.isActive(routeName));

let pivotRoute = this._router._routerMicrolib.getRoute(routeName) as Route;

return this._router._routerMicrolib.refresh(pivotRoute);
}

/**
The `routeWillChange` event is fired at the beginning of any
attempted transition with a `Transition` object as the sole
Expand Down
99 changes: 99 additions & 0 deletions packages/ember/tests/routing/router_service_test/refresh_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Route } from '@ember/-internals/routing';
import { RouterTestCase, moduleFor } from 'internal-test-helpers';

moduleFor(
'Router Service - refresh',
class extends RouterTestCase {
async ['@test RouterService#refresh can be used to re-run the model hooks of active routes'](
assert
) {
let parentCounter = 0;
this.add(
'route:parent',
Route.extend({
model() {
++parentCounter;
},
})
);

let childCounter = 0;
this.add(
'route:parent.child',
Route.extend({
model() {
++childCounter;
},
})
);

let sisterCounter = 0;
this.add(
'route:parent.sister',
Route.extend({
model() {
++sisterCounter;
},
})
);

await this.visit('/');
assert.equal(parentCounter, 1);
assert.equal(childCounter, 0);
assert.equal(sisterCounter, 0);

await this.routerService.refresh();
assert.equal(parentCounter, 2);
assert.equal(childCounter, 0);
assert.equal(sisterCounter, 0);

await this.routerService.refresh('application');
assert.equal(parentCounter, 3);
assert.equal(childCounter, 0);
assert.equal(sisterCounter, 0);

await this.routerService.transitionTo('parent.child');
assert.equal(parentCounter, 3);
assert.equal(childCounter, 1);
assert.equal(sisterCounter, 0);

await this.routerService.refresh('parent.child');
assert.equal(parentCounter, 3);
assert.equal(childCounter, 2);
assert.equal(sisterCounter, 0);

await this.routerService.refresh('parent');
assert.equal(parentCounter, 4);
assert.equal(childCounter, 3);
assert.equal(sisterCounter, 0);

await this.routerService.transitionTo('parent.sister');
assert.equal(parentCounter, 4);
assert.equal(childCounter, 3);
assert.equal(sisterCounter, 1);

await this.routerService.refresh();
assert.equal(parentCounter, 5);
assert.equal(childCounter, 3);
assert.equal(sisterCounter, 2);
}

async ['@test RouterService#refresh verifies that the provided route exists'](assert) {
await this.visit('/');

assert.throws(() => {
this.routerService.refresh('this-route-does-not-exist');
});
}

async ['@test RouterService#refresh verifies that the provided route name corresponds with an active route'](
assert
) {
await this.visit('/');

assert.throws(() => {
this.routerService.refresh('parent.child');
});
}
}
);

0 comments on commit bdc223c

Please sign in to comment.