{"id":34907,"date":"2026-09-08T19:45:38","date_gmt":"2026-09-08T17:45:38","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=34907"},"modified":"2026-10-01T02:44:15","modified_gmt":"2026-10-01T00:44:15","slug":"router-resources-loading-data-with-the-angular-router","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/","title":{"rendered":"Router Resources: Loading Data with the Angular Router"},"content":{"rendered":"<p><em>Signal-based resolvers: parallel instead of waterfall, blocking or non-blocking, plus a look at Signal Stores<\/em><\/p>\n<p>Resolvers are as old as the Angular Router itself. They load data before a route is activated and return an Observable or a Promise for it. In a world where data access increasingly goes through <code>resource<\/code>, <code>rxResource<\/code>, and <code>httpResource<\/code>, that feels out of place. With version 22.2, the router therefore gains an alternative in developer preview: <strong>Router Resources<\/strong>. They not only fit Signals better, they also bring a performance benefit, because the router loads them in parallel instead of one after another.<\/p>\n<p>This article explains the new API, shows both flavors using our demo application Flights42, and then looks at how Router Resources work together with Signal Stores.<\/p>\n<p><em>Update: This article has been revised for the final release of Angular 22.2. The first version was based on the prerelease 22.2.0-next.5, which behaved differently in some details.<\/em><\/p>\n<p>\ud83d\udcc2 <a href=\"https:\/\/github.com\/angular-architects\/flights42\/tree\/22.2\">Source code<\/a> (branch: <code>22.2<\/code>)<\/p>\n<h2>What Are Router Resources?<\/h2>\n<p>With Router Resources, a route gets a <code>resources<\/code> property that returns ordinary resources. The router takes care of their lifecycle and passes the results on to the component.<\/p>\n<p>The second reason for the new API is at least as important as the nicer interface: <strong>performance<\/strong>. The router processes classic resolvers sequentially along the route hierarchy. If the parent route needs 2 seconds for its data and the child route 3, the user waits 5 seconds for the navigation. Router Resources, by contrast, all start at the same time, even when they block. In the same example, the navigation now takes only 3 seconds, as long as the slowest resource:<\/p>\n<p><img decoding=\"async\" src=\".\/waterfall.png\" alt=\"Timing diagram: Two resolvers taking 2 and 3 seconds run one after another and block the navigation for 5 seconds. As Router Resources, both run in parallel and the navigation completes after 3 seconds.\" \/><\/p>\n<p>Besides such <strong>blocking Router Resources<\/strong>, Router Resources can also be defined as <strong>non-blocking<\/strong>. This means the router doesn't wait at all. It activates the route immediately and hands the still-loading resource to the component, which then renders the loading state itself.<\/p>\n<h2>Setting Up Router Resources<\/h2>\n<p>The feature is enabled via <code>withRouterResources<\/code> when configuring the router:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/app\/app.config.ts\n\nimport {\n  provideRouter,\n  withComponentInputBinding,\n  withRouterResources,\n} from &#039;@angular\/router&#039;;\n\n[...]\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    [...]\n    provideRouter(routes, withComponentInputBinding(), withRouterResources()),\n  ],\n};<\/code><\/pre>\n<p>Router Resources ship in Angular 22.2 as a developer preview. The API is public and essentially complete, but details may still change before it is declared stable. In addition, <code>withComponentInputBinding<\/code> is used so that the router binds the results of the resources to the component as inputs.<\/p>\n<h2>Blocking Router Resources<\/h2>\n<p>With this preparation in place, the first Router Resource can be defined. The route for editing a passenger loads the record before the component appears:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/app\/domains\/ticketing\/ticketing.routes.ts\n\n{\n  path: &#039;passenger-edit\/:id&#039;,\n  component: PassengerEdit,\n  resources: (ctx) =&gt; ({\n    passenger: createSimplePassengerResource(ctx.params),\n  }),\n},<\/code><\/pre>\n<p>The <code>resources<\/code> function runs in an injection context and receives a <code>ResourceContext<\/code>. It provides <code>params<\/code>, <code>queryParams<\/code>, <code>fragment<\/code>, and <code>data<\/code> as Signals. The factory function derives the id from them and creates a perfectly ordinary <code>httpResource<\/code>:<\/p>\n<pre><code class=\"language-typescript\">\/\/ [...]\/feature-booking\/passenger-edit\/simple-passenger-resource.ts\n\nimport { computed, inject, Signal } from &#039;@angular\/core&#039;;\nimport { Params } from &#039;@angular\/router&#039;;\n\nimport { PassengerClient } from &#039;..\/..\/data\/passenger-client&#039;;\n\nexport function createSimplePassengerResource(params: Signal&lt;Params&gt;) {\n  const passengerClient = inject(PassengerClient);\n  const id = computed(() =&gt; Number(params()[&#039;id&#039;] ?? 0));\n  return passengerClient.findPassengerResourceById(id);\n}<\/code><\/pre>\n<p>Without any further ado, such a resource is <strong>blocking<\/strong>. Just like with a resolver, the router waits until the value is available and only then activates the route. Thanks to <code>withComponentInputBinding<\/code>, it's not the resource itself that ends up in the component, but the already unwrapped value:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/app\/domains\/ticketing\/feature-booking\/passenger-edit\/passenger-edit.ts\n\n@Component({ [...] })\nexport class PassengerEdit {\n  [...]\n  protected readonly passenger = input&lt;Passenger&gt;(initPassenger);\n}<\/code><\/pre>\n<p>This is the same input a resolver populated before. For the component, the switch is invisible, which makes migration pleasant. If the route parameter changes later while the component is reused, the resource fetches the new value on its own, because <code>ctx.params<\/code> is a Signal.<\/p>\n<p>One detail deserves attention: the <code>httpResource<\/code> from the <code>PassengerClient<\/code> has a default value, an empty passenger. In the prereleases of 22.2, such a resource didn't block, because from the router's point of view a value was already present. Anyone who wanted to block had to do without the default value. The final 22.2 release instead looks solely at the loading state: the router waits until the resource's <code>isLoading<\/code> switches to <code>false<\/code>. A default value no longer stands in the way of blocking.<\/p>\n<h2>Non-Blocking Router Resources<\/h2>\n<p>Navigation shouldn't always wait for data. Often it's better to show the target page right away and make the loading state visible there. That's exactly what <code>nonBlocking<\/code> is for. The demo's luggage management uses it for its detail route:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/app\/domains\/luggage\/feature-luggage\/luggage.routes.ts\n\nimport { nonBlocking, Routes } from &#039;@angular\/router&#039;;\n\n[...]\n\n{\n  path: &#039;:id&#039;,\n  component: LuggageDetail,\n  resources: (ctx) =&gt; ({\n    luggage: nonBlocking(createLuggageResource(ctx.params)),\n  }),\n},<\/code><\/pre>\n<p>The factory function <code>createLuggageResource<\/code> is structured like the passenger example and delegates to the <code>LuggageClient<\/code>. Its loader is deliberately slow so the effect becomes visible, and it reports an unknown piece of luggage as an error:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/app\/domains\/luggage\/data\/luggage-client.ts\n\nfindLuggageById(id: Signal&lt;number&gt;) {\n  return resource({\n    params: id,\n    loader: async ({ params: id }) =&gt; {\n      \/\/ Deliberately delayed to make the loading state visible\n      await new Promise((resolve) =&gt; setTimeout(resolve, 2000));\n      const luggage = this.getLuggage().find((item) =&gt; item.id === id);\n      if (!luggage) {\n        throw new Error(`Luggage ${id} not found`);\n      }\n      return luggage;\n    },\n    defaultValue: initLuggage,\n  });\n}<\/code><\/pre>\n<p>The router now activates the route immediately. In this case, the component doesn't receive the unwrapped value but the complete <code>Resource<\/code> as its input:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/app\/domains\/luggage\/feature-luggage\/luggage-detail\/luggage-detail.ts\n\n@Component({ [...] })\nexport class LuggageDetail {\n  readonly luggage = input.required&lt;Resource&lt;Luggage&gt;&gt;();\n}<\/code><\/pre>\n<p>This makes all of the resource's state Signals available in the template. The template shows the loading state via <code>isLoading<\/code>. For the error case, it relies on another addition in Angular 22.2, the <code>@boundary<\/code> block:<\/p>\n<pre><code class=\"language-html\">&lt;!-- [...]\/luggage\/feature-luggage\/luggage-detail\/luggage-detail.html --&gt;\n\n@boundary {\n  @let resource = luggage();\n  @let item = resource.value();\n\n  @if (resource.isLoading()) {\n    &lt;p&gt;Loading luggage \u2026&lt;\/p&gt;\n  } @else {\n    &lt;form&gt; [...] &lt;\/form&gt;\n  }\n} @error {\n  &lt;p&gt;Luggage could not be loaded.&lt;\/p&gt;\n}<\/code><\/pre>\n<p>If the loader fails, <code>value()<\/code> throws the error as an exception so that it doesn't go unnoticed. Until now, a template therefore had to check the <code>error()<\/code> signal first and was only allowed to read <code>value()<\/code> in the success case. A <code>@boundary<\/code> block catches such errors for the enclosed part of the template and renders its <code>@error<\/code> block instead. Navigating to <code>\/luggage\/9999<\/code> in the demo shows the message from the <code>@error<\/code> block after the delay. The link back to the overview is outside the boundary and therefore stays visible in any case. Since the resource has a default value, <code>item<\/code> is never <code>undefined<\/code> either, which saves the template one more check.<\/p>\n<p>The division of labor is clear: blocking resources deliver finished values and guarantee that the target page is complete. Non-blocking resources deliver the loading lifecycle along with the data and leave rendering the intermediate state to the target page.<\/p>\n<p><div style=\"\nmargin: 8px 0;\npadding: 22px;\nborder: 1px solid #e5e7eb;\nborder-radius: 14px;\nbackground: #f8fafc;\n\">NOTE<\/p>\n<h3 style=\"margin-top:0\">Modern Angular<\/h3>\n<\/p>\n<p style=\"margin:0 0 12px 0\"><strong style=\"display:inline-block; background:#16a34a; color:#fff; padding:4px 10px; border-radius:999px; font-size:0.85em\">\u2713 Already updated to Angular 22!<\/strong><\/p>\n<p>You'll find more on resources, Signals, and modern Angular architecture in my new eBook Modern Angular. It covers Signals, architecture, testing, AI assistants, and practical solutions for modern business applications.<\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/modern-book\"><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/01\/cover-klein.png\" width=\"400\" alt=\"Modern Angular - Signal-first, Architecture-first, Practice-first\" style=\"cursor:pointer !important\"><\/a><\/p>\n<p><a style=\"cursor:pointer !important\" href=\"https:\/\/www.angulararchitects.io\/modern-book\">More about the book \u2192<\/a>\n<\/div>\n<\/p>\n<h2>Reload and Redirect<\/h2>\n<p>Two more capabilities set Router Resources apart from resolvers. The first concerns reloading. Anyone who wanted to fetch a resolver's data again had to re-activate the route, for instance with <code>onSameUrlNavigation: &#039;reload&#039;<\/code>. That repeats the entire navigation, including guards and resolvers. A Router Resource, on the other hand, can be reloaded on its own, without the router starting a navigation.<\/p>\n<p>With a blocking resource, however, the component only receives the value, not the resource itself. Access to it is provided by the <code>ActivatedRoute<\/code>, which offers all of the route's resources under their keys:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/app\/domains\/ticketing\/feature-booking\/passenger-edit\/passenger-edit.ts\n\nimport { ActivatedRoute } from &#039;@angular\/router&#039;;\n\n[...]\n\n@Component({ [...] })\nexport class PassengerEdit {\n  [...]\n  private readonly passengerResource =\n    inject(ActivatedRoute).resources?.[&#039;passenger&#039;];\n\n  protected reload(): void {\n    \/\/ Reloads only this resource without re-activating the route\n    this.passengerResource?.reload();\n  }\n}<\/code><\/pre>\n<p>The <code>?.<\/code> accounts for the fact that, for demonstration purposes, the application can also run the same route with a resolver. In that case, there is no resource. A button in the template calls <code>reload<\/code>. Since the router binds the value of a blocking resource to the input via an effect, the new record arrives in the component on its own once loaded. In the demo, this also resets the form, because <code>passengerModel<\/code> is a <code>linkedSignal<\/code> on the input: local changes are discarded, and the record comes fresh from the server.<\/p>\n<p>The second capability concerns missing data. The <code>httpResource<\/code> from the blocking example reports an unknown passenger as an error, since the API responds with 404. With a blocking resource, the router then cancels the navigation and emits a <code>NavigationError<\/code>. The user stays on the previous page. Usually, a redirect is the better reaction, for example to a not-found page. For this, the loader throws a <code>RedirectCommand<\/code>. Since 22.2, the router officially supports throwing a <code>RedirectCommand<\/code>, in guards and resolvers as well. The router cancels the navigation and redirects to the given URL.<\/p>\n<p>Since <code>httpResource<\/code> has no loader of its own, the demo falls back on <code>resource<\/code> for this. The new factory function calls the <code>PassengerClient<\/code> and translates the 404 error into a redirect:<\/p>\n<pre><code class=\"language-typescript\">\/\/ [...]\/feature-booking\/passenger-edit\/passenger-resource.ts\n\nimport { HttpErrorResponse } from &#039;@angular\/common\/http&#039;;\nimport { inject, resource, Signal } from &#039;@angular\/core&#039;;\nimport { Params, RedirectCommand, Router } from &#039;@angular\/router&#039;;\nimport { firstValueFrom } from &#039;rxjs&#039;;\n\nimport { PassengerClient } from &#039;..\/..\/data\/passenger-client&#039;;\n\nexport function createPassengerResource(params: Signal&lt;Params&gt;) {\n  const passengerClient = inject(PassengerClient);\n  const router = inject(Router);\n\n  return resource({\n    params: () =&gt; Number(params()[&#039;id&#039;] ?? 0),\n    loader: async ({ params: id }) =&gt; {\n      try {\n        return await firstValueFrom(passengerClient.findById(String(id)));\n      } catch (error) {\n        if (error instanceof HttpErrorResponse &amp;&amp; error.status === 404) {\n          \/\/ Cancels the navigation and redirects instead of failing it\n          throw new RedirectCommand(router.parseUrl(&#039;\/not-found&#039;));\n        }\n        throw error;\n      }\n    },\n  });\n}<\/code><\/pre>\n<p>In the demo, the route <code>passenger-edit\/:id<\/code> now uses this factory function instead of <code>createSimplePassengerResource<\/code>. The route <code>not-found<\/code> shows a plain notice page. Navigating to <code>passenger-edit\/999999<\/code> takes you there without the target page ever appearing. This only works with blocking resources, because only there is the router still waiting for the result. With non-blocking resources, the navigation has already completed, an error ends up in <code>error()<\/code>, and the component decides for itself how to react.<\/p>\n<h2>Router Resources and Signal Stores<\/h2>\n<p>In many applications, it's not the route that loads the data but a Signal Store. There are three ways to combine such a store with Router Resources.<\/p>\n<p><strong>The store hands out its resource.<\/strong> If a store defines its resource itself, for instance in <code>withProps<\/code>, and exposes it, the route can use it directly. The demo shows this with the <a href=\"https:\/\/github.com\/angular-architects\/flights42\/blob\/22.2\/src\/app\/domains\/ticketing\/feature-booking\/passenger-edit\/passenger-store.ts\">PassengerStore<\/a>. The factory function for the route passes the id Signal to the store and returns the store's resource:<\/p>\n<pre><code class=\"language-typescript\">\/\/ [...]\/feature-booking\/passenger-edit\/shared-passenger-resource.ts\n\nexport function createSharedPassengerResource(params: Signal&lt;Params&gt;) {\n  const store = inject(PassengerStore);\n  const id = computed(() =&gt; Number(params()[&#039;id&#039;] ?? 0));\n  store.load(id);\n  return store.passenger;\n}<\/code><\/pre>\n<p>Store and router now share the same resource. The router waits for it and binds its value to the component, and anyone who needs the value or loading state outside the route reads it from the store.<\/p>\n<p><strong>Waiting for the store.<\/strong> If the store encapsulates its resource, a Router Resource of its own can wait for it: the loader sets the id on the store and waits until the store's loading state ends. The demo shows this in <a href=\"https:\/\/github.com\/angular-architects\/flights42\/blob\/22.2\/src\/app\/domains\/ticketing\/feature-booking\/passenger-edit\/store-passenger-resource.ts\">store-passenger-resource.ts<\/a>. A helper function like <a href=\"https:\/\/github.com\/angular-architects\/flights42\/blob\/22.2\/src\/app\/domains\/shared\/util-common\/wait-for.ts\">waitFor<\/a> bridges the gap between the Signal world and the Promise world of the loader: it observes the Signal with an <code>effect<\/code> and resolves a Promise as soon as the expected value arrives. This works, but I'm not particularly fond of it: the resource exists only so that the router has something to wait for, and it wraps a mechanism a second time that is already complete on its own.<\/p>\n<p><strong>A dedicated resource for the route.<\/strong> My favorite is the approach from the previous sections: an ordinary resource created specifically for the route that delegates data access to a service. This also matches the intention behind Router Resources. They often need knowledge about the concrete use case, for example when they redirect to another route if data is missing. That knowledge belongs to the route, not to a store that is used in several places. The store remains responsible for the state the component manages after the navigation.<\/p>\n<p>After consulting with the Angular team, I can say that they consider this a good solution as well. The router is the source of truth for routing parameters. The component receives the value of the Router Resource as an input and can pass it on to the store.<\/p>\n<p>Alternatively, the store could access the router itself and synchronize the current routing parameters with its state. Personally, I prefer going through the component, because in my view the store shouldn't know about UI details and therefore shouldn't know about the router either.<\/p>\n<h2>Learn More: Angular Architecture Workshop (Remote, Interactive, Advanced)<\/h2>\n<p>Become an expert in enterprise-wide and long-lived Angular applications with our Angular Architecture Workshop!<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/sujet-en.jpg\" alt=\"Angular Architecture Workshop\" style=\"width:600px; max-width:100%; display: block; margin: 0 auto 0 0\" \/><\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/en\/training\/advanced-angular-architecture-workshop\/\">German Version<\/a> | <a href=\"https:\/\/www.angulararchitects.io\/en\/training\/advanced-angular-architecture-workshop\/\">English Version<\/a><\/p>\n<h2>Summary<\/h2>\n<p>Router Resources bring the loading of route data into the Signal world. A route declares its data as ordinary resources, the router starts them all in parallel and binds the results to the component as inputs. The old resolver waterfall is gone. In the example, the waiting time shrank from 5 to 3 seconds. With Angular 22.2, the API is public as a developer preview, and a default value no longer prevents a resource from blocking.<\/p>\n<p>Blocking resources behave like resolvers with a better interface, non-blocking ones deliver the loading lifecycle directly to the target page, where a <code>@boundary<\/code> block catches the error case. Via the <code>ActivatedRoute<\/code>, a resource can be reloaded without a new navigation, and a <code>RedirectCommand<\/code> in the loader redirects when data is missing. For the interplay with Signal Stores, one rule has proven itself for me: the route gets its own resource that delegates to a service, and the store takes care of the state after the navigation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Signal-based resolvers: parallel instead of waterfall, blocking or non-blocking, plus a look at Signal Stores Resolvers are as old as the Angular Router itself. They load data before a route is activated and return an Observable or a Promise for it. In a world where data access increasingly goes through resource, rxResource, and httpResource, that [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":34905,"comment_status":"open","ping_status":"open","sticky":true,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[18],"tags":[],"class_list":["post-34907","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Router Resources: Loading Data with the Angular Router - ANGULARarchitects<\/title>\n<meta name=\"description\" content=\"Router Resources in Angular 22: load data with resources, not resolvers \u2013 parallel instead of waterfall, blocking or not, with demo and Signal Stores.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Router Resources: Loading Data with the Angular Router - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"Router Resources in Angular 22: load data with resources, not resolvers \u2013 parallel instead of waterfall, blocking or not, with demo and Signal Stores.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-08T17:45:38+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-01T00:44:15+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/social-sujet.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2400\" \/>\n\t<meta property=\"og:image:height\" content=\"1260\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Manfred Steyer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/social-sujet.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/\"},\"author\":{\"name\":\"Manfred Steyer\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\"},\"headline\":\"Router Resources: Loading Data with the Angular Router\",\"datePublished\":\"2026-09-08T17:45:38+00:00\",\"dateModified\":\"2026-10-01T00:44:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/\"},\"wordCount\":1877,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/hero.png\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/\",\"name\":\"Router Resources: Loading Data with the Angular Router - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/hero.png\",\"datePublished\":\"2026-09-08T17:45:38+00:00\",\"dateModified\":\"2026-10-01T00:44:15+00:00\",\"description\":\"Router Resources in Angular 22: load data with resources, not resolvers \u2013 parallel instead of waterfall, blocking or not, with demo and Signal Stores.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/hero.png\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/hero.png\",\"width\":1920,\"height\":1080},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Router Resources: Loading Data with the Angular Router\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\",\"name\":\"Manfred Steyer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Router Resources: Loading Data with the Angular Router - ANGULARarchitects","description":"Router Resources in Angular 22: load data with resources, not resolvers \u2013 parallel instead of waterfall, blocking or not, with demo and Signal Stores.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/","og_locale":"en_US","og_type":"article","og_title":"Router Resources: Loading Data with the Angular Router - ANGULARarchitects","og_description":"Router Resources in Angular 22: load data with resources, not resolvers \u2013 parallel instead of waterfall, blocking or not, with demo and Signal Stores.","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/","og_site_name":"ANGULARarchitects","article_published_time":"2026-09-08T17:45:38+00:00","article_modified_time":"2026-10-01T00:44:15+00:00","og_image":[{"width":2400,"height":1260,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/social-sujet.png","type":"image\/png"}],"author":"Manfred Steyer","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/social-sujet.png","twitter_misc":{"Written by":"Manfred Steyer","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/"},"author":{"name":"Manfred Steyer","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a"},"headline":"Router Resources: Loading Data with the Angular Router","datePublished":"2026-09-08T17:45:38+00:00","dateModified":"2026-10-01T00:44:15+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/"},"wordCount":1877,"commentCount":0,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/hero.png","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/","name":"Router Resources: Loading Data with the Angular Router - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/hero.png","datePublished":"2026-09-08T17:45:38+00:00","dateModified":"2026-10-01T00:44:15+00:00","description":"Router Resources in Angular 22: load data with resources, not resolvers \u2013 parallel instead of waterfall, blocking or not, with demo and Signal Stores.","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/hero.png","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2026\/09\/hero.png","width":1920,"height":1080},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/router-resources-loading-data-with-the-angular-router\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Router Resources: Loading Data with the Angular Router"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a","name":"Manfred Steyer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","caption":"Manfred Steyer"}}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/34907","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=34907"}],"version-history":[{"count":8,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/34907\/revisions"}],"predecessor-version":[{"id":35049,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/34907\/revisions\/35049"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/34905"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=34907"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=34907"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=34907"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}