Angular 2+ модальное окно с помощью router-outlet

В одном из прошлых постов я рассказывала как можно на Angular сделать модальное окно с помощью ng-template. Решение вышло не сказать, чтобы простым.

Сегодня я хочу рассказать о более легком способе — реализация через роутинг.
Если нужно сразу решение, то вот пример. В статье я подробно остановлюсь на некоторых моментах.

Для того, чтобы в Angular приложении заработала навигация нужно сделать ряд доработок.

base href

Для начала следует задать базовый адрес приложения, прописав в теге head файла index.html:

<base href="/">

В случае онлайн примеров, например, в Plunker,  адрес устанавливается динамический, так что мы не можем его указать жестко. Вместо этого прописываем его добавление ‘на лету’

<script>document.write('<base href="' + document.location + '" />');</script>

 

RouterModule

Далее добавляем RouterModule в список import декоратора ngModule.

@NgModule({
   imports: [ BrowserModule, RouterModule ],
   declarations: [ AppComponent ],
   bootstrap: [ AppComponent ]
})

Для того, чтобы TypeScript не ругался, нужно в начале файла RouterModule импортировать.

import {RouterModule} from '@angular/router';

Впрочем, как минимум, последняя версия WebStorm поддерживает авто импорт, так что это процесс сильно упрощается.

Модуль роутера

Затем необходимо создать модуль роутера.

Кстати, если вы работает через Angular cli, то можно при создании модуля указать опцию —routing, тогда будет сгенерирован и файл роутера.

В моем примере  скелет роутера вышел таким:

    const appRoutes: Routes = [
        { 
            path: '',
            redirectTo: '/home',
            pathMatch: 'full' 
        },
        {   
            path: 'home',
            component: HomeComponent 
        },
        { 
            path: 'signin',
            component: SignInModalComponent,
            outlet: 'popup'
        }
   ];

path — url, а component — тот компонент, которые отображается по данному url.

Так по урлу  site-name/home будет отображаться HomeComponent.

Также нужно учесть, что браузер запускает приложение с / в адресной строке.

Нам же, например, нужно перенаправить на домашнюю страницу, поэтому мы прописываем редирект. Свойство pathMatch: ‘full’  обязательно для редиректа, чтобы указать роутеру, что HomeComponent нужно подгружать только если имеется полное соответствие пути.

В последнем объекте мы видим свойство outlet, которое нас как раз приближает к решению задачи открытия модального окна. Самое время познакомиться с router-outlet.

router-outlet

Итак, финальным штрихом будет добавление в шаблон router-outlet.
Директива помечает где будет отображаться компонент, соответствующий конкретному урлу.

Я ее добавила в шаблон корневого app компонента.




<div>
    <router-outlet></router-outlet>
    <a [routerLink]="[{ outlets: { 'popup': [ 'signin'] }}]" skipLocationChange> Open Popup </a>
    <router-outlet name="popup"></router-outlet>
</div>



Тут же мы видим дополнительный router-outlet, c именем popup. Как раз то, что мы указали в роутинге.

Неименнованный  router-outlet может быть только один, а именнованных несколько.

Директива [routerLink] связывает элемент (в данном случае тег a) с роутером.

Она в квадратных скобках, так как идет речь о выводе данных из ts кода в шаблон, так называемое, property binding.

skipLocationChange указывает, что отображение пути в поисковой строке браузера меняться не будет.

Содержимое — это объект  с единственным свойством outlets, которое содержит другой объект, связанный с одним или более outlet именем. В нашем случае это только ‘poup’ свойство, чье значение ссылается на signin роутер.

Закрытие попапа реализуется таким образом:

    onClose() {

        this.router.navigate([{ outlets: { popup: null }}]);

    }

Мы просто устанавливаем значение null для именованного outlet, тем самым очищая его контент.

Вот собственно и все. Если появились вопросы — с удовольствием отвечу.

Хотите быть в курсе новых статей?

  1. Здравствуйте! Подскажите пожалуйста, сделал всё как описано в статье, но во время опытной эксплуатации выяснилось, что при отображении outlets: popup содержимое базового outlets пропадает. Причём пропадает именно это содержимое, весь дополнительный HTML из шаблона AppComponent остаётся. К сведению у меня Angular 7. А если закрыть outlets: popup, как описано в статье, то содержимое базового outlets снова появляется. Буду благодарен за помощь.

  2. Здравствуйте, Алексей! На 7 ангуляре я это решение не проверяла. Плюс скажу больше — я в результате использую более сложный вариант, описанный в статье http://www.front-nika.ru/ru/angular2-modal-okno-c-pomoshhyu-ng-template/. Честно говоря, уже не помню почему его решила выбрать, но как минимум на 6 ангуляре работает 🙂