
После прочтения статьи "Порог вхождения в Angular 2 — теория и практика" у меня появилось желание показать, как можно пробросить все роуты Angular 2 через роутер Laravel 5.
Идея следующая
- в директории
resources/views/backendбудет лежать представление, являющееся точкой входа для всех роутов Angular 2. Для каждого роута Angular 2, роутер Laravel 5 будет нас перенаправлять на это представление; - под каждый Angular 2 роут в директиве
@RouteConfigнам придется создать копию в роутере Laravel; - все роуты Angular 2, по которым подтягиваются шаблоны, будут иметь вид вида
/templates/SomeComponent.main, и будут запрашиваться роутером Laravel 5 по пути видаresources/views/frontend/SomeComponent/main.blade.php
Приступим
Чтобы не запутаться, разобьем все представления в директории
resources/views на 2 подпапки: backend— для представлений, которые Laravel 5 использует напрямую;frontend(в статье будет использоватьсяfrontend, но кто-то пожелает переименовать, например вtemplates) — для всех шаблонов, которые будут использоваться в Angular 2.
1) Front-end
Допустим, у нас есть уже созданный root-компонент
app.component.ts, а так же 2 компонента: components/MainComponent.ts, который будет загружаться по умолчанию, и components/EditComponent.ts. Мы хотим указать в директиве
@RouteConfig 2 роута: один '/' с именем Home, ведущий на MainComponent, а второй '/edit' с именем Edit, ведущий на EditComponent. //app.component.ts @RouteConfig([ { path: '/', name: 'Home, component: MainComponent, useAsDefault: true }, { path: '/edit', name: 'Edit', component: EditComponent } ]) @Component({ 'directives': [ROUTER_DIRECTIVES], 'selector': 'app', 'template': '<router-outlet></router-outlet>' }) export class AppComponent { constructor () {} }
Далее необходимо задать для компонентов их шаблоны:
//components/MainComponent.ts @Component({ 'selector': 'state-template', 'templateUrl': '/templates/MainComponent.main' }) export class MainComponent { ... } //components/EditComponent.ts @Component({ 'selector': 'state-template', 'templateUrl': '/templates/EditComponent.main' }) export class EditComponent { ... }
2) Back-end
Первым делом, в роутере Laravel 5 продублируем все основные роуты Angular 2. Все подобные роуты мы будем направлять в
AngularRoutesController.//routes.php Route::get('/', [ 'uses' => 'MyApp\AngularRoutesController@index', 'as' => 'ngHome' ]); Route::get('/edit', [ 'uses' => 'MyApp\AngularRoutesController@index', 'as' => 'ngEdit' ]);
В
AngularRoutesController мы будем просто рендерить представление, являющееся точкой входа, для Angular 2:public function index() { return view('backend.content'); }
Представление
views/backend/content.blade.php должно содержать в себе тег, в который будет грузиться Angular 2 приложение, у нас это app.@extends('backend.layout') @section('backend.content') <app> @include('backend.loading') </app> @include('backend.scripts-import') @stop
Для роутов Angular 2, ведущих к темплейтам, создадим еще 1 Laravel 5 маршрут, который будет перенаправлять запрос на контроллер
AngularTemplatesController://routes.php Route::get('/templates/{template}', [ 'uses' => 'MyApp\AngularTemplatesController@index', 'as' => 'ngTemplates' ]);
Внутри
AngularTemplatesController нам необходимо добавить к $template, в котором содержится часть пути к представлению с шаблоном, имя нашей папки с шаблонами Angular 2 — frontend.public function index($template) { $templatePath = 'frontend.' . $template; if (!view()->exists($templatePath)) { throw new NotFoundHttpException(); } return view($templatePath); }
Итог
В результате, все Angular 2 шаблоны, которые будут запрашиваться по URL-адресу вида
/templates/SomeComponent.main будут браться по пути вида resources/views/frontend/SomeComponent/main.blade.php. Мы сможем использовать шаблонизатор Blade в шаблонах Angular 2.Нюансы
Поскольку в шаблонизаторе Blade и в шаблонах Angular 2 используется одинаковый синтаксис с двойными фигурными скобками
{{ ... }}, для корректной обработки двойных фигурных скобок, относящихся к Angular 2, необходимо будет ставить перед ними символ @.Этот символ позволит шаблонизатору Blade игнорировать такие конструкции, для последующего из разбора Angular 2.
<div>{{ bladeVariable }}</div> <li *ngFor="#file of files" class="list-group-item"> @{{ file.name }} </li>
Репозиторий с примером.
