I have set up my app so that I have a Recipe Book
which has a list of Recipies
which when I click on a Recipe it then shows the Recipe Details
in a nested route. This then also has a button that when clicked loads the ingredients in a nested route inside the Recipes Details
.
So far the routing seems to work, except when I try to navigate to another Recipe
. If the Ingredients
tray(route) is active then it will change Recipe and collapse the Ingredients
Route, If I then try and navigate (without opening the Ingredients) I get the following error:
Uncaught (in promise): Error: Outlet is not activated
Error: Outlet is not activated
It looks like I the router needs Ingredients
to be active or else it doesn't understand the nested route. Thats my take on it but not sure how to fix it or when I went wrong.
single-recipe-book-page.component.html
<app-tray class="recipe-list">
<app-recipe-list [recipe]="recipe"></app-recipe-list>
</app-tray>
<router-outlet></router-outlet>
recipe-detail.component.html
<app-tray class="recipe">
The routing has worked and loaded recipe.
</app-tray>
<router-outlet></router-outlet>
ingredients-list.component.html
<app-tray class="ingredients-list">
Recipe Ingredients have loaded.
</app-tray>
app.routes.ts (updated)
export const routerConfig : Route[] = [
{
path: 'recipe-books',
children: [
{
path: ':id', component: SingleRecipeBookPageComponent,
children: [
{
path: 'recipes',
children: [
{ path: ':id', component: RecipeDetailComponent,
children: [
{ path: '', component: IngredientsListComponent },
{ path: 'ingredients', component: IngredientsListComponent }
]
},
{ path: 'new', component: IngredientsListComponent },
{ path: '', component: RecipeDetailComponent }
]
},
{ path: '', redirectTo: 'recipes', pathMatch: 'full' }
]
},
{ path: '', component: RecipeBooksPageComponent }
]
},
{ path: 'ingredients', component: IngredientsComponent },
{ path: '', redirectTo: 'recipe-books', pathMatch: 'full' },
{ path: '**', redirectTo: 'recipe-books', pathMatch: 'full' }
];
This route is invalid and you should get an error for it.
A route either needs to have a
component
, aredirectTo
, orchildren
.If an empty path route has no children it also should have
pathMatch: 'full'
.I guess what you want is
Where
DummyComponent
is a component with an empty view. You can reuse the sameDummyComponent
for all these paths.This might help someone else.
I was getting this error. I have checked all my defined
routes
in my route file, thepath
andcomponents
are defined correctly.The reason of getting this error was that I forgot to add reference of my
service
inapp.module.ts
which was being used in one of my component to get data fromRestApi
.So, always add service reference in app.module.ts in
providers
section, immediately after creating service.TLDR; answer :
There's a new feature in Angular router that sounds related to this problem, but isn't - as far as I can tell - a direct solution for it. The new option is
runGuardsAndResolvers = 'pathParamsChange'
and it affects when Angular checks guards and resolvers - and crucially whether it runs this outlet check.So before I found the new option:
context.outlet.component
(wherecomponent
is a getter that throws).So to fix I'd just need to make
shouldRun == false
somehow.And
shouldRun
is simplyshouldRunGuardsAndResolvers(...)
so if that can be made to return false then it won't try to create a component in the 'wrong' place.So the solution is quite simple:
Currently
runGuardsAndResolvers
has quite a few options, but the one I'm using just always returnsfalse
which is equivalent tonever
which really ought to be made into an option. But that's how I found out about the new router features :-)Also if you have two levels you need to put this at both (or possibly just the highest) level:
Further reading on resolvers: https://blog.angularindepth.com/new-in-angular-v7-1-updates-to-the-router-fd67d526ad05