Skip to content

Commit

Permalink
feat(ComponentRenderer): Split render middleware into pre/post render…
Browse files Browse the repository at this point in the history
… middleware
  • Loading branch information
brandonroberts committed Apr 1, 2016
1 parent cc01ac2 commit 59b7ad9
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 13 deletions.
29 changes: 21 additions & 8 deletions lib/component-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,20 @@ import { fromCallback, compose } from './util';
import { Route } from './route';
import { Middleware, identity, provideMiddlewareForToken } from './middleware';

export const RENDER_MIDDLEWARE = new OpaqueToken(
'@ngrx/router Render Middleware'
export const PRE_RENDER_MIDDLEWARE = new OpaqueToken(
'@ngrx/router Pre Render Middleware'
);

export const useRenderMiddleware = provideMiddlewareForToken(
RENDER_MIDDLEWARE
export const POST_RENDER_MIDDLEWARE = new OpaqueToken(
'@ngrx/router Post Render Middleware'
);

export const usePreRenderMiddleware = provideMiddlewareForToken(
PRE_RENDER_MIDDLEWARE
);

export const usePostRenderMiddleware = provideMiddlewareForToken(
POST_RENDER_MIDDLEWARE
);

export interface RenderInstruction {
Expand All @@ -44,7 +52,10 @@ export interface ResolvedInstruction {

@Injectable()
export class ComponentRenderer {
constructor(@Inject(RENDER_MIDDLEWARE) private _middleware: Middleware[]) { }
constructor(
@Inject(PRE_RENDER_MIDDLEWARE) private _preMiddleware: Middleware[],
@Inject(POST_RENDER_MIDDLEWARE) private _postMiddleware: Middleware[]
) { }

render(
route: Route,
Expand All @@ -57,14 +68,15 @@ export class ComponentRenderer {
.map<RenderInstruction>(component => {
return { component, injector, providers };
})
.let<RenderInstruction>(compose(...this._middleware))
.let<RenderInstruction>(compose(...this._preMiddleware))
.map<ResolvedInstruction>(instruction => {
const providers = Injector.resolve(instruction.providers);
const component = instruction.component;

return { providers, component, ref, dcl }
})
.mergeMap(instruction => this.renderComponent(instruction));
.mergeMap(instruction => this.renderComponent(instruction))
.let<ComponentRef>(compose(...this._postMiddleware));
}

renderComponent({ component, providers, ref, dcl }: ResolvedInstruction) {
Expand All @@ -85,6 +97,7 @@ export class ComponentRenderer {
}

export const COMPONENT_RENDERER_PROVIDERS = [
useRenderMiddleware(identity),
usePreRenderMiddleware(identity),
usePostRenderMiddleware(identity),
new Provider(ComponentRenderer, { useClass: ComponentRenderer })
];
2 changes: 1 addition & 1 deletion lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ export { LocationChange, Location } from './location';
export { Middleware, createMiddleware } from './middleware';
export { RouteParams } from './route-params';
export { useLocationMiddleware, useRouteSetMiddleware, RouteSet, NextRoute } from './route-set';
export { useRenderMiddleware, RenderInstruction } from './component-renderer';
export { usePreRenderMiddleware, usePostRenderMiddleware, RenderInstruction } from './component-renderer';
export { Routes, Route, IndexRoute } from './route';
export { useTraversalMiddleware } from './match-route';
65 changes: 61 additions & 4 deletions spec/component-renderer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import { Injector, provide, DynamicComponentLoader, ElementRef } from 'angular2/core';
import { Location } from '../lib/location';
import { ComponentRenderer, RENDER_MIDDLEWARE, useRenderMiddleware } from '../lib/component-renderer';
import {
ComponentRenderer,
PRE_RENDER_MIDDLEWARE,
POST_RENDER_MIDDLEWARE,
usePreRenderMiddleware,
usePostRenderMiddleware
} from '../lib/component-renderer';
import { Route } from '../lib/route';
import { createMiddleware } from '../lib/middleware';

Expand All @@ -27,7 +33,8 @@ describe('Component Renderer', function() {
beforeEach(() => {
injector = Injector.resolveAndCreate([
ComponentRenderer,
provide(RENDER_MIDDLEWARE, { useValue: [] }),
provide(PRE_RENDER_MIDDLEWARE, { useValue: [] }),
provide(POST_RENDER_MIDDLEWARE, { useValue: [] }),
provide(DynamicComponentLoader, {useClass: MockDCL})
]);

Expand Down Expand Up @@ -60,7 +67,7 @@ describe('Component Renderer', function() {
});
});

describe('Middleware', () => {
describe('Pre Middleware', () => {
let route: Route = { component: TestComponent };
let providers = [];
let elementRef = {};
Expand All @@ -86,7 +93,8 @@ describe('Component Renderer', function() {

injector = Injector.resolveAndCreate([
ComponentRenderer,
useRenderMiddleware(renderMiddleware),
usePreRenderMiddleware(renderMiddleware),
provide(POST_RENDER_MIDDLEWARE, {useValue: []}),
provide(DynamicComponentLoader, {useClass: MockDCL})
]);

Expand Down Expand Up @@ -122,4 +130,53 @@ describe('Component Renderer', function() {
});
});
});

describe('Post Middleware', () => {
let route: Route = { component: TestComponent };
let providers = [];
let elementRef = {};
let middlewareSpy = jasmine.createSpy('middleware');
let renderMiddleware;
let render;

beforeEach(() => {
renderMiddleware = createMiddleware(function(instruction$) {
return (componentRef$) => componentRef$.map((componentRef) => {
middlewareSpy();

return false;
});
}, []);

injector = Injector.resolveAndCreate([
ComponentRenderer,
usePostRenderMiddleware(renderMiddleware),
provide(PRE_RENDER_MIDDLEWARE, {useValue: []}),
provide(DynamicComponentLoader, {useClass: MockDCL})
]);

renderer = injector.get(ComponentRenderer);
loader = injector.get(DynamicComponentLoader);
});

beforeEach(() => {
render = renderer.render(route, injector, <ElementRef>elementRef, loader, providers);
});

it('should execute after rendering', (done) => {
render.subscribe(() => {
expect(loader.loadNextToLocation).toHaveBeenCalled();
expect(middlewareSpy).toHaveBeenCalled();
done();
});
});

it('can modify the component ref', (done) => {
render.subscribe((componentRef) => {
expect(loader.loadNextToLocation).toHaveBeenCalled();
expect(componentRef).toEqual(false);
done();
});
});
});
});

0 comments on commit 59b7ad9

Please sign in to comment.