Как использовать несколько выходов маршрутизатора в angular2?

У меня есть основной router-outlet, который используется для отображения экрана входа в систему (/login) и экрана основного содержимого (который отображается после входа в систему) (/main).

Когда пользователь находится на экране контента, я хочу показать навигационную панель сверху с двумя вариантами (скажем, «Обзор», «Полезная информация»). Эта панель навигации является общей для OverviewComponent и InsightsComponent.

Под этой навигационной панелью я хочу показать другой маршрутизатор-выход, который будет загружать OverviewComponent или InsightsComponent в зависимости от того, что пользователь щелкает в навигационной панели. Если я укажу «/overview» и / «insights» в качестве маршрута, он сразу покажет мне соответствующий компонент, но не панель навигации.

Ниже приведена моя текущая конфигурация маршрутизации (это неправильно):

const appRoutes: Routes = [
  { path: 'main', component:  MainComponent},
  { path: 'overview', component:  OverviewComponent},
  { path: 'insights', component: InsightsComponent },
  { path: 'login', component: LoginComponent },
  { path: '',
    redirectTo: '/login',
    pathMatch: 'full'
  },
  { path: '**', component: PageNotFoundComponent }
];

Пожалуйста, дайте мне знать, сможем ли мы добиться этого в angular2 angular4. Я использую следующую версию:

"@angular/core": "^4.0.0"
"@angular/router": "^4.0.0"
"@angular/cli": "1.0.1"

******************Попытка 2 - Все еще не работает******************

const appRoutes: Routes = [
  { path: 'main',
    children: [
      { path: '', component: MainComponent },
      { path: 'overview', component:  OverviewComponent },
      { path: 'insights', component: InsightsComponent },
    ]

  },
  { path: 'login', component: LoginComponent },
  { path: '',
    redirectTo: '/login',
    pathMatch: 'full'
  },
  { path: '**', component: PageNotFoundComponent }
];

*******Попытка 2 - Код Sudo со всеми компонентами - Все еще не работает *******

//app.component.html

<router-outlet></router-outlet>


//app.module.ts

const appRoutes: Routes = [
  { path: 'main',
    children: [
      { path: '', component: MainComponent },
      { path: 'overview', component:  OverviewComponent },
      { path: 'insights', component: InsightsComponent },
    ]

  },
  { path: 'login', component: LoginComponent },
  { path: '',
    redirectTo: '/login',
    pathMatch: 'full'
  },
  { path: '**', component: PageNotFoundComponent }
];

//login.component.html
<div class="text-center vertical-center">
    <form>
        <div class="horizontal">
            <label for="">Email</label>
            <input class="form-control" type="text" name="" value="">
        </div>
        <div class="horizontal">
            <label for="">Password</label>
            <input class="form-control" type="password" name="" value="">
        </div>
        <button class="btn btn-primary" (click)="navigate()">Login</button>
    </form>
</div>

//login.component.ts
navigate() {
    this.router.navigate(['./main']);
  }

//main.component.html

<app-header></app-header>
<router-outlet></router-outlet>


//app.header.html

<ul class="nav navbar-nav">
               <li class=""><a routerLink="/main/overview" routerLinkActive="active">OVERVIEW</a></li>
                <li class=""><a routerLink="/main/insights" routerLinkActive="active">INSIGHTS</a></li>
            </ul>

//overview.html
<p>This is overview section</p>

//insights.html
<p>This is insights section</p>

**********Попытка 3 - Работает *********

const appRoutes: Routes = [
  { path: 'main', component: MainComponent,
    children: [
      { path: '', component: MainComponent },
      { path: 'overview', component:  OverviewComponent },
      { path: 'insights', component: InsightsComponent },
    ]

  },
  { path: 'login', component: LoginComponent },
  { path: '',
    redirectTo: '/login',
    pathMatch: 'full'
  },
  { path: '**', component: PageNotFoundComponent }
];

person Deepak    schedule 03.05.2017    source источник
comment
Могу я посмотреть, как выглядит ваш main.component.html?   -  person Saiyaff Farouk    schedule 03.05.2017
comment
Не удалось решить эту проблему, добавив routerLink в заголовок приложения? Если это не работает, какую ошибку вы получаете? -Вы можете редактировать вопрос с определенным кодом. Было бы намного яснее.   -  person Saiyaff Farouk    schedule 03.05.2017
comment
У вас есть два варианта: вы можете определить дочернюю розетку маршрутизатора или вторичную (вспомогательную) розетку маршрутизатора. Дополнительную информацию см. в документации: angular.io/docs/ts/latest/guide. /router.html   -  person DeborahK    schedule 03.05.2017
comment
Привет, Сайяфф, я пробовал routerLink до href, это тоже не сработало. Ошибка не выдается. Когда я нажимаю «Обзор» или «Insights», на экране отображается компонент «Обзор» или «Insight» без заголовка, который присутствует в основном компоненте.   -  person Deepak    schedule 03.05.2017
comment
Привет, Дебора. В примере показана только одна розетка маршрутизатора. У меня 2 роутера. Есть ли примеры, которые вы можете использовать для розеток детского маршрутизатора?   -  person Deepak    schedule 03.05.2017
comment
Я такой глупый! Я пропустил добавление MainComponent в качестве компонента в module.ts const appRoutes: Routes = [ { path: 'main', component: MainComponent, children: [ { path: '', component: MainComponent }, { path: 'overview', component: OverviewComponent }, { path: 'insights', component: InsightsComponent }, ] }, { path: 'login', component: LoginComponent }, { path: '', redirectTo: '/login', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; Теперь он работает нормально...   -  person Deepak    schedule 03.05.2017


Ответы (2)


Итак, если я правильно понял вопрос, вы хотите, чтобы экран входа в систему был изначально и после входа пользователя, вы хотите, чтобы он видел /main, где отображается навигация. И экран входа в систему, и главное приложение должны иметь разный макет.

У нас есть аналогичный случай и использование LayoutComponent. Вот упрощенный пример.

// This is main component that get's bootstrapped that has 'top-level' router.
@Component({selector: 'app', template: '<router-outlet></router-outlet>'})
class AppComponent {}

// main router config
// Here AuthModule has router with login and logout configured and LoginGuard
// redirect the user to /auth/login when she is not authenticated.
// We're using lazy-loading but you can use direct component instead
export const APP_ROUTES: Routes = [
  {path: '', redirectTo: 'main', pathMatch: 'full'},
  {path: 'auth', loadChildren: '../modules/+auth/auth.module#AuthModule'},
  {
    path: '',
    component: LayoutComponent,
    canActivate: [LoginGuard],
    children: [
      {path: 'main', loadChildren: '../modules/+main/main.module#MainModule'}
    ]
  }
];

// AuthModule/LoginComponent has own template and it will be rendered
// into 'top-level' router-outlet.

// LayoutComponent
// Here you define your main application layout that can include navigation
// and anything else that are global to the app. It has another router-outlet
// that get rendered when the layout is accessible (which in this case when the user is authenticated).
@Component({
  selector: 'app-layout',
  template: `
    <div id="wrapper">
      <app-sidebar></app-sidebar>
      <div id="page-wrapper" class="gray-bg dashboard-1" adjust-content-height>
        <router-outlet></router-outlet>
      </div>
    </div>
    <notifications></notifications>
    <error-modal></error-modal>
  `
})
export class LayoutComponent {}

// Auth/LoginComponent can have its own template that will have different layout from the main application

Таким образом, поток будет таким:

  • когда пользователь пытается загрузить / то она перенаправляется на /main
  • если пользователь не аутентифицирован, она перенаправляется на /auth/login, иначе она загружает /main

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ: обновлен репозиторий sickelap/ng-starter с примером приложения, которое имеет:

  • маршрутизация с отложенной загрузкой
  • макеты
  • и другие вещи
person sickelap    schedule 03.05.2017
comment
Но это здорово, на самом деле я хотел, чтобы мои представления загружались лениво. Я думал, что мой код выше загружается лениво. Только один вопрос: находится ли APP_ROUTES в основном app.component.ts (именно это и есть в коде) или является частью app.module.ts? - person Deepak; 03.05.2017
comment
Я храню APP_ROUTES в файле app.routes.ts и использую их в app.module.ts. После ответа на этот вопрос я начал думать, что было бы неплохо поделиться структурой проекта в качестве рабочего примера использования множества хороших вещей в использовании angular. Я знаю, что существует множество шаблонов и стартеров, но, как и все остальные, я хотел бы сделать это по-своему ™ :) Я создал репо github.com/sickelap/ng-starter, банкомат пуст, но сейчас работает над этим, и через несколько дней будет что-то полезное. - person sickelap; 03.05.2017
comment
Это потрясающе, спасибо. Да, в А2 так много классных вещей, о которых многие не знают, и иногда трудно найти фрагменты. Ваш стартовый набор наверняка многим поможет. Оставьте комментарий, когда это будет сделано, чтобы все мы могли взглянуть на это. Спасибо еще раз. Мне нравится "Твой путь" ;) - person Deepak; 03.05.2017
comment
Обновлен репо с примером приложения. Это незавершенная работа, и я буду время от времени обновлять ее, добавляя новые функции или предложения. мне очень понравилось - person sickelap; 03.05.2017

Я думаю, что понимаю, чего вы пытаетесь достичь. Могу ли я порекомендовать вам использовать переменную для имитации какого-либо изменения состояния и назначить ее для представления компонента. пусть ваш app.component.html содержит только выход маршрутизатора. создайте новый main.component.html, который реплицирует существующий component.html

`<app-header></app-header>`

замените href на *(click)="handleChange(<linkValue>)'"

Таким образом, каждая ссылка будет выглядеть, как показано ниже.

<ul class="nav navbar-nav"> <li class=""><a href="/main/overview">OVERVIEW</a></li>

handleChange метод: объявить текущую ссылку - public currentLink string; // or public currentLink: string = '<a default value>'; public handleChange(link: string) { this.currentLink = link; }

создать представление.компонент.

пример селектора <view [link]='currentLink'></view>

дать компоненту представления @Input() public link: string;

back to view.component.html 

<div id="overview" *ngIf="link = 'overview'">overview content</div> <div id="main" *ngIf="link = 'main'">overview content</div>

Затем вы можете реорганизовать их в отдельные дочерние компоненты.

Обзор: вы делаете заголовок приложения глобальным компонентом, который обрабатывает переменную «ссылка». Я бы порекомендовал взглянуть на ngRx или общие методы состояния приложения. Так как это может быть отличным способом управления пользовательским интерфейсом.

person verix    schedule 03.05.2017
comment
Спасибо за помощь Verix, теперь у меня все работает. Но да, это потенциальная альтернатива, которую я попробую. - person Deepak; 03.05.2017
comment
Превосходно! Я хотел бы знать ваше решение, если у вас есть время? Я много занимаюсь управлением состоянием и сложными рабочими процессами, так что это было достойное занятие для меня. Тем не менее, я хотел бы иметь альтернативу для подачи заявки! - person verix; 03.05.2017
comment
Конечно. Я обновил свой вопрос всеми своими попытками (с кодом Sudo). Начальный провал, а потом подъем! ;) - person Deepak; 03.05.2017