Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
angular/router
Search
Nikas Praninskas
May 17, 2015
Technology
450
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
angular/router
The New Angular Router
Nikas Praninskas
May 17, 2015
More Decks by Nikas Praninskas
See All by Nikas Praninskas
Static Site Generators with JavaScript
nikaspran
1
360
Move over, Gatsby - React Static in Practice
nikaspran
1
710
Web Components: The (near) Future of Web Development
nikaspran
2
4.1k
Other Decks in Technology
See All in Technology
TiDBファミリーにDWHが新登場!! TiDB最新情報 / TiDB update 202609
yoshiakiyamasaki
0
180
人にやさしく、AIにやさしく、書き手を選ばないIaCのガードレール再考 / Rethinking IaC Guardrails for Humans and AI Alike
kohbis
5
1.9k
いちAWSエンジニアのAI活用を振り返る #devio2026 / devio osaka 2026 kawahara
masahirokawahara
1
300
DORA_Metrics.pdf
wagnerfusca
1
140
AIに会社の文脈を理解させる技術~上流工程・非エンジニアにも広げるハーネスエンジニアリング実践~
ochtum
0
200
【ゲームメーカーズスクランブル2026】『Shadowverse: Worlds Beyond』UIとアニメーションで実現する最高のユーザー体験を叶えるプロトタイピング
cygames
PRO
1
710
Lambda MicroVMsが分からなすぎたので使い所を1から考えてみた
tsukuboshi
1
270
行動するAIのためのオントロジー | DevRev — Encraft #26.pdf
dvrv_tknrszk
2
650
『GOエコノミー 』(相乗りサービス) におけるスペック駆動開発
mot_techtalk
1
120
Confitura 2026
logico_jp
0
120
OpenClawでAzure DevOpsのWiki更新を自動化する - クラウドAIだけでは届かない場所へ
yutakaosada
0
140
Terraformを用いたJamf Pro構成のIaC, GitOps化への挑戦
yukun
0
120
Featured
See All Featured
Embracing the Ebb and Flow
colly
88
5.2k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
390
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
560
The Pragmatic Product Professional
lauravandoore
37
7.5k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
320
The agentic SEO stack - context over prompts
schlessera
0
950
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
510
Into the Great Unknown - MozCon
thekraken
41
2.7k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
340
Statistics for Hackers
jakevdp
799
230k
The Limits of Empathy - UXLibs8
cassininazir
1
690
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
860
Transcript
angular/router The New Angular Router
Hi, I’m Nikas Front end dev @ Wix.com/app-market @nikaspran github/nikaspran
nikas.praninskas.com
The next 45 minutes of your life Prior art What
is the New Angular Router? Migration Current state of affairs
Disclaimer: everything is Work In Progress
Prior art
What ARE frogs Routers?
Deep linking is awesome share information know at a glance
contextualize bookmark The ability to
Don’t break the back button The back button is free
and obvious It is very easy to be annoying if you break navigation
Structure for your app Forces you to modularize Makes apps
easy to understand
ngRoute The default Angular 1 routing solution
ngRoute - very simple .config(function($routeProvider){ $routeProvider .when('/user/:id', { templateUrl: 'user.html',
controller: 'UserCtrl', resolve: {...} }) .when('/user/:id/edit', { templateUrl: 'userEdit.html', controller: 'UserEditCtrl' }); }); One view per app One URL, one view <a href="user/123"></a> <a href="user/123/edit"></a> <div ng-view></div>
Good things come to those who wait .when('/user/:id', { ...,
resolve: { user: function($q) { var data = $q.defer(); //get user data from API return data.promise; } } }) Inject into controller from configuration Waits until promises resolve
Simple, but too simple Difficult to do things like modals
sidebars deep routes parallel views complex apps
UI Router The de facto Angular 1 routing solution
UI Router - much more powerful <a ui-sref="layout.user"></a> <a ui-sref="layout.user.edit(
{id: 123})"></a> <div ui-view="sidebar"></div> <div ui-view="content"></div> State based routing .config(function($stateProvider){ $stateProvider .state('layout', { abstract: true, templateUrl: 'layout.html' }) .state('layout.user', { views: { sidebar: { templateUrl: 'sidebar.html', controller: 'SidebarCtrl', resolve: {...} }, content: {...} } }) });
States are intuitive States describe architecture Not everything has to
have a URL Easy to link to parts of your application
Lots of utility <a ui-sref="user.edit({id: 123})"></a> <a href="/base/user/123"></a>
<ui-sref-active> $state.is() $state.go() $state.href() $state.includes() Lots of utility …
Customizability is very important and UI Router does a pretty
good job: christopherthielen/ui-router-extras onEnter, onExit, $stateChange*, ...
…up to a point Do something complex enough and you
start fighting the router
Something complex enough
Same URL, different background state
Multiple paths that preserve history 1. Open App Market 2.
Click App icon Use direct link to App (eg. via social) wix.com/app-market/:appName/overview
we spent way too much time fighting our tools at
the time, we did a fork still not obvious how to do it all
Angular 2 is coming Can we do better with a
clean slate?
Introducing The New Angular Router
Introducing The New Angular Router
Introducing Component Router
Goals
Be customizable… Let people do complex interesting surprising amazing things
…but have great defaults Make it obvious intuitive quick easy
to learn and use
Multiple views /foo/bar foo bar foo bar parallel nested OR
State-like reverse routing Automatically deep link to components <a router-link="user"
router-params="{id: 123}"></a> <a href="./user/123"></a>
State-like reverse routing Link to multiple components at once sidebar
content mainPage <a router-link="mainPage"></a>
Thought experiment: The router is one of the most important
parts of an application
So… If it is designed for Angular 2
If it is designed for Angular 2 but also works
with Angular 1
If it is designed for Angular 2 but also works
with Angular 1 We have a migration plan! ng1 ng2
Proposed migration scenario ng1 ng1 ng1 ng1 ng1 ng1 Angular
1 app
Proposed migration scenario ng1 ng1 ng1 ng2 ng1 ng1
Proposed migration scenario ng1 ng2 ng1 ng2 ng2 ng1
Proposed migration scenario ng2 ng2 ng2 ng2 ng2 ng2 Angular
2 app
ま よ た ね ぃ み む ょ じ を
り ぉ ね ぼ り ぉ け ば や わ ゎ お ら ゆ ろ り ぉ け ば や わ ゎ お ら ゆ じ ゃ で り ぐ き な ゕ ゟ た ょ を こ で ぷ お じ ぁ だ ど ぬ す っ ら び ぅ ぬ だ ざ ま よ た ね ぃ み む ょ じ を り ぉ ね ぼ び ぃ ぅ や こ そ ぶ や あ ゝ ぼ ゆ ぺ み ひ じ え わ ぶ す ぞ ぷ ゑ っ ぞ ほ だ Show me the code already ま よ た ね ぃ み む ょ じ を り ぉ ね ぼ ろ り ぉ け ば や わ ゎ お ら ゆ ほ ぞ ぁ ろ り ぉ け ば や わ ゎ お び ぃ ぅ や こ そ ぶ や あ ゝ ぼ ゆ ぺ み ひ じ え わ ぶ す ぞ ぷ ゑ っ ぞ ほ だ ま よ た ね ぃ み む ょ じ を ろ り ぉ け ば や わ ゎ お ら ゆ ほ び ぃ ぅ や こ そ ぶ や あ ゝ ぼ ゆ ぺ み ひ じ え わ ぶ す ぞ ぷ ゑ っ ま よ た ね ぃ み む ょ じ を り ぉ ね ぼ ろ り ぉ け ば や わ ゎ お ら ゆ ほ ぞ ぁ ろ り ぉ け ば や わ ゎ び ぃ ぅ や こ そ ぶ や あ ゝ ぼ ゆ ぺ み ぶ す ぞ ぷ ゑ っ ぞ ほ だ り ぉ け ば や わ ゎ お ら ゆ ほ ぞ ぁ ろ り ぉ け ば や わ ゎ お ぉ け ば や わ ゎ お ら ゆ ほ ろ り ぉ け ば や わ ゎ お ら ゆ け ば や わ ゎ お ら ゆ ほ ぞ ぁ ろ り ぉ け ば や わ ゎ お ら ゆ を こ で ぷ お じ ぁ だ ど う え を こ で ぷ お じ ぁ だ ど う え ぬ す っ ら び ぅ ぬ だ ざ ぬ す っ ら び ぅ ぬ だ ざ ぬ す っ ら び ぅ ぬ だ ざ ぶ す ぞ ぷ ゑ っ ぞ ほ だ ゝ ぼ ゆ ぺ み あ ゝ ぼ ゆ ぺ み あ ゝ ぼ ゆ ぺ み あ ゝ ぼ ゆ ぺ み ぬ す っ ら び ぅ ぬ す っ ら び ぅ ぬ だ ざ ぬ す っ ら び ぅ ぬ だ ざ ぬ す っ ら び ぅ ぬ だ ざ ぬ す っ ら び ぅ ぬ あ ゝ ぼ ゆ ぺ み ゝ ぼ ゆ ぺ み ま よ た ね び ぃ ぅ や こ そ ぶ ま よ た ね ぃ み
Angular 2.x import {ListComponent} from './list'; import {EditComponent} from './edit';
@Component({...}) @View({template: '...'}) @RouteConfig([ {path: '/', component: ListComponent}, {path: '/edit/:id', component: EditComponent} ]) class AppComponent() { ... }
Angular 1.x $componentMapper .setCtrlNameMapping(comp => comp + 'Ctrl'); $componentMapper .setTemplateMapping(comp
=> comp + '.html'); AppController.$routeConfig([ {path: '/', component: 'list'}, {path: '/edit/:id', component: 'edit'} ]); function AppController() { ... }
Static configuration {path: '/', component: 'list'}, {path: '/edit/:id', component: 'edit'}
{path: '/', component: ListComponent}, {path: '/edit/:id', component: EditComponent} ng2 ng1 === easy to port
Component Router Components Outlets Instructions Pipeline
Component Router Components Outlets Instructions Pipeline
So what’s a component anyway? Template Controller Router
Template - ng2 @View({template: '...'}) @View({templateUrl: '...'})
Template - ng1 $componentMapper .setTemplateMapping(function (compName) { return templatePath; });
./components/my-comp/my-comp.html myComp Uses component convention by default: Customize as you want:
“Controller” - ng2 class MyComp() {...}
Controller - ng1 $componentMapper .setCtrlNameMapping(function (compName) { return controllerName; });
Adds “Controller” by default: Customize as you want: MyCompController myComp
Router Each component can have a child router Child routers
manage their sub-URLs
You can release it as an artifact They can mount
and use it SO,if you build an amazing component with deep linking
Router - ng2 @RouteConfig([ {path: '/', redirectTo: '/main'}, {path: '/main',
component: MainComp}, {path: '/other', components: {}, as: 'other'} ])
Router - ng1 function MainController($router) { $router.config([...]); } function MainController()
{...}; MainController.$routeConfig([...]);
Component Router Components Outlets Instructions Pipeline
Outlet - think ui-view <div ng-outlet></div> <div ng-outlet="left"></div> {path: '/',
components: { default: 'posts', left: 'users' }}
Component Router Components Outlets Instructions Pipeline
Instruction Holds all the context for a transition: Outlets, path,
parameters, ...
Component Router Components Outlets Instructions Pipeline
Pipeline - it’s middleware Takes Instruction Transforms it ..with side
effects $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep
E.g.: pipeline in Angular 1.x $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep
$activateStep Pipeline
Let’s ask the router to go somewhere $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep
$runCanActivateHookStep $loadTemplatesStep $activateStep router.navigate('users/123')
Router generates the instruction $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep
router.navigate('users/123') recognize(): instruction matchedUrl component router children: Instruction[]
Once more unto the pipeline! $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep
$activateStep matchedUrl component router children: Instruction[]
$setupRoutersStep $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep matchedUrl component router
children: Instruction[] Add child instruction routers
$initLocalsStep $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep matchedUrl component router
children: Instruction[] locals Add locals: $router, $routeParams
$runCanDeactivateHookStep $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep matchedUrl component router
children: Instruction[] locals Visit old outlets; run canDeactivate()
$runCanActivateHookStep $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep matchedUrl component router
children: Instruction[] locals Visit new outlets; run canActivate()
$loadTemplatesStep $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep matchedUrl component router
children: Instruction[] locals template Load templates, add to instruction
$activateStep $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep matchedUrl component router
children: Instruction[] locals template Recursively activate outlets (ctrl, tmpl, ...)
Final step… Update $location: http://someHost/base/users/123 … and done!
Pipeline - it’s customizable $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep
Up to you
E.g.: let’s add resolve $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep
resolveStep
Create our step factory .factory('resolveStep', function ($q, $injector) { return
function resolve(instruction) { }; })
Recurse over instructions .factory('resolveStep', function ($q, $injector) { return function
resolve(instruction) { var promises = []; return instruction.router.traverseInstruction( instruction, queueResolves ).then(function () { return $q.all(promises); }); }; })
Get config from instruction .factory('resolveStep', function ($q, $injector) { return
function resolve(instruction) { var promises = []; function queueResolves(instruction) { var cfg = getResolveConfigFrom(instruction); } return instruction.router.traverseInstruction( instruction, queueResolves ).then(function () { return $q.all(promises); }); }; })
Queue the resolution .factory('resolveStep', function ($q, $injector) { return function
resolve(instruction) { var promises = []; function queueResolves(instruction) { var cfg = getResolveConfigFrom(instruction); var resolve = $q.when($injector.invoke(cfg.value)); promises.push(resolve.then(function (resolved) { })); } return instruction.router.traverseInstruction( instruction, queueResolves ).then(function () { return $q.all(promises); }); }; })
Add it to locals .factory('resolveStep', function ($q, $injector) { return
function resolve(instruction) { var promises = []; function queueResolves(instruction) { var cfg = getResolveConfigFrom(instruction); var resolve = $q.when($injector.invoke(cfg.value)); promises.push(resolve.then(function (resolved) { instruction.locals[cfg.key] = resolved; })); } return instruction.router.traverseInstruction( instruction, queueResolves ).then(function () { return $q.all(promises); }); }; })
Insert it into the pipeline .config(function ($pipelineProvider) { var steps
= $pipelineProvider.steps; var atPosition = steps.indexOf('$runCanDeactivateHookStep) + 1; //insert resolveStep after $runCanDeactivateHookStep steps.splice(atPosition, 0, 'resolveStep'); $pipelineProvider.config(steps); })
End result $setupRoutersStep $initLocalsStep $runCanDeactivateHookStep $runCanActivateHookStep $loadTemplatesStep $activateStep resolveStep Part
of the pipeline Called on every transition
> implications Standardized extension Make it suit your app Publish
and prosper
Component Router Components Outlets Instructions Pipeline Other “stuff”
Sticky components This is how it currently works Under consideration
and desirable
Dynamic loading Add new routes @ runtime: function SomeController($router) {
$router.config([...]); }
Recursive components Not sure how practical, but why not
Migration
ng1 + ngComponentRouter ng2 ng 1.5 + new router Some
things we know
And some we don’t ng1 + X ng1 + ngComponentRouter
ng2 ng 1.5 + new router ?
ngRoute is too simple to worry about
Migration strategies from UI Router are a TODO item But
one can dream…
Multi-components are sort of like states $router.config([{ as: 'category', path:
'/:category', components: { sidebar: 'Sidebar', content: 'Category' } }]); $stateProvider .state('category', { url: '/:category', views: { sidebar: { templateUrl: '...', controller: '...' }, content: { templateUrl: '...', controller: '...' } } }); ui-router compRouter
Directives are sort of similar <a router-link="user" router-params="{id: 123}"></a> <a
ui-sref="user({id: 123})"></a> ~== ui-router compRouter
What about what’s missing? Well…
Pipeline! e.g. we saw how to add resolve we can
fake $stateChangeEvents someone write an adapter? :)
How can we prepare? Use similar conventions Component-like architecture Component-like
file structure
Write unit tests UI Router configuration is testable Write now,
then verify migration later http://nikas.praninskas.com/test-ui-router Component Router should be even easier
Current $state of affairs //TODO: draw something totally awesome like
robots and lasers and stuff and maybe a cat
Documentation!
Read the source, Luke: github.com/angular/router
github.com/angular/angular …no wait, now it’s:
but only temporarily…
Codebase is a bit of a mess: 1.x has not
worked for over a month everything in ng2 repo until build is stable still working out core issues (i.e. reverse routing)
When? Originally slated for 1.4
…but probably not anymore: :(
June-July? (my somewhat educated guess)
In place of a summary Designed from the ground up;
New ideas for the future; Lessons learned from the past; Not yet ready.
Thank you! nikas.praninskas.com github/nikaspran @nikaspran