Skip to content

An example of how you can implement backend-driven modals in web applications built with Laravel, Inertia.js, Vue, and Tailwind CSS.

Notifications You must be signed in to change notification settings

climberdigital/laravel-inertia-modals

Repository files navigation

RUS | ENG

Для чего этот проект?

В этом репозитории вы найдёте мой личный пример реализации динамических модальных окон в веб-приложениях на стеке Laravel + Inertia.js + Vue + Tailwind CSS.

Представленный подход должен отлично подойти проектам, практикующим DDD или его "облегчённые" формы (модульный монолит и т.п.), но в целом он подойдёт любому проекту, использующему Inertia.js для SPA-фронтенда в Laravel-приложении.

Мой подход не потребует дополнительных манипуляций с HTTP-заголовками, middleware или внедрения сторонних пакетов (кроме Axios на фронтенде). Вам даже не нужно прибегать к использованию глобальных данных Inertia через её HandleInertiaRequests middleware, и этот подход легко масштабируется.

Я написал подробный пост об этом в блоге на своём сайте, который тоже поможет вам лучше понять, как и зачем используется мой подход к реализации модальных окон в Laravel и Inertia.js.

Запуск проекта

  1. В командной строке перейдите в корень проекта
  2. cp .env.example .env
  3. composer install
  4. npm install
  5. npm run build
  6. php artisan key:generate
  7. php artisan migrate --seed (используется база данных SQLite по умолчанию)
  8. php artisan test — для тестирования

Запускать проект в Docker или через Laravel Herd и другие локальные серверы — на ваше усмотрение. Подробные инструкции по установке и запуску проекта на Laravel доступны в официальной документации фреймворка.

Основные принципы работы

Модальные окна в большинстве случаев бывают двух типов: окно подтверждения действия и окно с формой ввода. Используя подход, представленный в этом репозитории, на фронтенде вы лишь добавляете "обёртку" для рендеринга модальных окон и задаёте базовые условия их отображения и разделения по типу, а контроль за содержимым этих модальных окон вы полностью делегируете бэкенду.

Несмотря на превосходные инструменты, которые нам дарят современные фронтенд-фреймворки и библиотеки, я убеждён, что фронтенд должен оставаться "тупым", и архитектурные решения приложения не должны подстраиваться под него (кроме исключительных случаев, разумеется). Поэтому практически всю динамическую часть кода модальных окон мы отдаём бэкенду, а фронтенд получает только готовые объекты данных, которые он рендерит соответствующим образом — в установленных условиях и ограничениях.

Модальные окна на фронтенде

На фронтенде вам доступен конфигурируемый компонент-триггер, отвечающий за отправку XHR-запроса на сервер с помощью Axios. Он получает только URL эндпоинта, по которому делает запрос, а сервер отвечает JSON с данными нужного модального окна. Этот компонент можно стилизовать извне, и он имеет слот для добавления любого текста или иконки для кнопки.

Основная "обёртка" модального окна добавляется в главный layout в качестве компонента Vue. Для управления состоянием модального окна используется собственный composable, содержащий экспортируемое и "реактивное" состояние (state). Это позволяет управлять модальным окном из разных точек интерфейса, используя этот composable в качестве своего рода глобальной шины, не связанной с глобальным состоянием стрыницы Inertia.

Для рендеринга модальных окон в проекте есть два компонента: для подтверждения действия и для формы ввода. Компонент модальной формы ввода обслуживается собственным "конструктором" динамических форм, который рендерит любую комбинацию полей ввода, которые приходят вместе с изначальными значениями (заполненные или пустые) с бэкенда при вызове этого модального окна.

Модальные окна на бэкенде

На бэкенде такие вызовы модальных окон будут приходить в любой стандартный контроллер и обрабатываться, как и любой HTTP-запрос в Laravel, а ответ будет формироваться из DTO со строгой типизацией и возвращаться в формате JSON. На фронтенде ответ затем обрабатывается в том же компоненте-триггере, который изначально вызывает модальное окно, а данные ответа передаются в глобальный Vue composable, содержащий "реактивные" параметры состояния.

Весь код, относящийся к модальным окнам, добавлен в директорию src/ в корне проекта, которая подключена к автозагрузке в качестве неймспейса Domain\. В остальном это пустое стандартное Laravel-приложение, за исключением добавления middleware HandleInertiaRequests, обязательного для работы Inertia.js на бэкенде.

Все взаимодействия происходят с фиктивным списком пользователей, который генерируется фабриками Laravel и сидируется соответствующей командой artisan.

В приложении нет никакой авторизации, так как это просто демо, не предназначенное для публичного применения в продакшене.

Рекомендации

  1. Чтобы проще было понимать логику, начинайте свой путь из файла routes/web.php, где указаны все эндпоинты приложения, включая те, которые обслуживают модальные окна. С них вы можете перейти в контроллеры и следовать добавленной мной подробной документации в коде.

  2. В этом демо я не применяю TypeScript для простоты восприятия кода разработчиками разных уровней подготовки и опыта. Но, если вы работаете с TypeScript, то, разумеется, вы сможете добиться строгой типизации и на фронтенде, сделав этот подход к реализации модальных окон ещё более отказоустойчивым.

  3. На бэкенде, в неймспейсе Domain\Admin\Users вы найдёте классы CreateModal и EditModal. Связывать их контрактом или нет — решать вам, в зависимости от требований вашего проекта и команды. Технически это просто фабрики полей ввода для форм, и нехватку любого из их методов перехватят тесты.

Послесловие

Я использовал похожий подход к реализации модальных окон уже не один год в продакшене, в коммерческих клиентских проектах, но данная реализация — это его актуальная версия, и она была вдохновлена концепцией пакета InertiaUI/Modal от Паскаля Балье, известного разработчика в экосистеме Laravel.

Его подход предполагает глубокую интеграцию в жизненном цикле запроса в Inertia и дополнительную манипуляцию HTTP-заголовками и middleware в Laravel, но, на мой взгляд, это излишнее усложнение для большинства проектов. Поэтому, если вы хотите иметь меньше на одну зависимость в проекте и больше контроля, то, я надеюсь, вы найдёте мой более "лёгкий" вариант реализации модальных окон полезным.

About

An example of how you can implement backend-driven modals in web applications built with Laravel, Inertia.js, Vue, and Tailwind CSS.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published