Angular 2 throwing error: Outlet is not activated

六眼飞鱼酱① 提交于 2019-12-10 01:33:37

问题


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' }
];

回答1:


This route is invalid and you should get an error for it.

{ path: '' },

A route either needs to have a component, a redirectTo, or children.

If an empty path route has no children it also should have pathMatch: 'full'.

I guess what you want is

{ path: '', component: DummyComponent, pathMatch: 'full' },

Where DummyComponent is a component with an empty view. You can reuse the same DummyComponent for all these paths.




回答2:


This might help someone else.

I was getting this error. I have checked all my defined routes in my route file, the path and components are defined correctly.

The reason of getting this error was that I forgot to add reference of my service in app.module.ts which was being used in one of my component to get data from RestApi.

So, always add service reference in app.module.ts in providers section, immediately after creating service.

imports: [
   BrowserModule,
   HttpModule,
   ......
 ],

providers: [
    AuthService, 
    ........ // Here, service reference
]



回答3:


TLDR; answer :

{
      path: ':question',
      runGuardsAndResolvers: () => false   // blocks component creation
}

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:

  • I was stepping through into angular code - and the actual error occurs here (highlighted I n red) at context.outlet.component (where component is a getter that throws).

  • So to fix I'd just need to make shouldRun == false somehow.

  • And shouldRun is simply shouldRunGuardsAndResolvers(...) 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:

 {
        path: 'contactus',
        component: ContactUsComponent,

        children: [
            {
                path: 'topics',
                pathMatch: 'full'
            },

            {
                path: 'faq',
                component: FaqPanelComponent
            },

            { 
                path: 'test',
                component: ContactusTopicListComponent
            },
            {
                path: ':category',

                children: 
                [
                    {
                        path: ':question',
                        runGuardsAndResolvers: () => false   // blocks component creation
                    }
                ]
            }
        ]
    },

Currently runGuardsAndResolvers has quite a few options, but the one I'm using just always returns false which is equivalent to never 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:

        {
            path: ':category',
            runGuardsAndResolvers: () => false,

            children: 
            [
                {
                    path: ':question',
                    runGuardsAndResolvers: () => false
                }
            ]
        }

Further reading on resolvers: https://blog.angularindepth.com/new-in-angular-v7-1-updates-to-the-router-fd67d526ad05



来源:https://stackoverflow.com/questions/40413133/angular-2-throwing-error-outlet-is-not-activated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!