pbStudio: Меню и страница «О нас»



Навигация по урокам:

Настройка меню сайта


Добавляем меню на сайт.
1. Создаем ресурсы:
  • О компании (about)
  • Портфолио (portfolio)
  • Услуги (services)
  • Контакты (contacts)
Главный ресурс скрываем из меню, для этого отмечаем галочку «Скрыть из меню»

2. Вывод меню в шаблоне
Добавляем код меню в чанк header (core/App/elements/chunks/header.tpl)
<nav class="navbar navbar-expand-lg">
    <div class="container">
        <a class="navbar-brand" href="{'site_url'|config}">
            <img src="/assets/images/logo.svg" width="40" height="40" alt="{'site_name'|config}">
            {'site_name'|config}
        </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar"
                aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbar">
            <ul class="navbar-nav me-auto d-flex align-items-center">
                {'!pbMenu'|snippet: [
                    'level' => 2,
                    'tpl' => '@INLINE <li class="nav-item level-{$level}">
                                    <a class="nav-link{$resourse_id === $id ? " active": ""}" 
                                        href="{$uri}" {$attributes}
                                    >{$menutitle ?: $pagetitle}</a>
                                </li>'
                    'tplParent' => '@INLINE <li class="nav-item dropdown">
                                    <a href="#" 
                                        class="nav-link dropdown-toggle" 
                                        role="button" 
                                        data-bs-toggle="dropdown" 
                                        aria-expanded="false" {$attributes}
                                    >{$menutitle ?: $pagetitle}</a>
                                    <ul class="dropdown-menu">{$wrapper}</ul>
                                </li>'
                ]}
            </ul>
        </div>
    </div>
</nav>

Страница «О нас»


Для этой страницы нам потребуется создавать 2 блока: Hero и Team

Блок Hero

Продолжаем добавлять блоки в файле core/App/Models/Resource.php

1. Настройка блока.
Для этого блока нам потребуется всего лишь 2 поля — заголовок и описание.
Block::make('Hero')
    ->fields([
        Field::make('Title')->required(),
        Field::make('Description')
            ->type('richtext')
            ->required(),
    ]),

2. Создаем чанк core/App/elements/chunks/hero.tpl
<section class="hero my-5">
    <div class="row">
        <div class="col-12 col-md-4">
            <h1>{$title}</h1>
        </div>
        <div class="col-12 pt-2 {$modx->resource->id == 2 ? 'col-md-8' : 'col-md-6 ms-auto'}">
            {$description}
        </div>
    </div>
</section>

Блок Team



Это более сложный блок, в котором можно добавить сотрудников, текстовые описания и информацию о вакансиях.

Для реализации этого блока мы создадим зависимые поля, которые будут отображаться в зависимости от выбранного типа элемента. Всего предусмотрено три типа:
  • Картинка
  • Текст
  • Вакансия
Варианты отображения полей:
Если выбран тип "Картинка", отображаются поля:
  • Картинка
  • Имя
  • Должность
Если выбран тип "Текст", отображаются поля:
  • Заголовок
  • Описание
Если выбран тип "Вакансия", отображаются поля:
  • Заголовок
  • Описание
  • Кнопка (с текстом и ссылкой)
1. Настройка блока.
Block::make('Team')
    ->fields([
        // Создаем поле таблица
        Field::make('Team')
            ->type('table')
            ->fields([
                // Поле выбора типа элемента
                Field::make('Type')
                    ->type('select')
                    ->options([
                        'image' => 'Image',
                        'text' => 'Text',
                        'vacancy' => 'Vacancy',
                    ])
                    ->default('image')
                    ->required(),
                
                // Поля для типа "image" (сотрудник)
                Field::make('Image')
                    ->type('image')
                    ->sourcePath('/assets/images/')
                    ->required()
                    ->hidden('type', '!=', 'image'),
    
                Field::make('Name')
                    ->width(50)
                    ->required()
                    ->hidden('type', '!=', 'image'),
    
                Field::make('Position')
                    ->width(50)
                    ->required()
                    ->hidden('type', '!=', 'image'),
                
                // Поля для типов "text" и "vacancy"
                Field::make('Title')
                    ->required()
                    ->hidden('type', '=', 'image'),
    
                Field::make('Description')
                    ->type('richtext')
                    ->required()
                    ->hidden('type', '=', 'image'),
                
                // Поле только для вакансий
                Field::make('Button')
                    ->type('button')
                    ->required()
                    ->hidden('type', '!=', 'vacancy'),
            ])
            ->columns([
                // Кастомная колонка, показываем картинку, а если ее нет, то заголовок
                Column::make('Image')
                    ->label('Image / Title')
                    ->renderIf([
                        Column::make('Image')->render('image'),
                        Column::make('Title')
                    ]),
                
                // Группируем имя и должность
                Column::make('Team')->group([
                    Column::make('Name'),
                    Column::make('Position')
                ])
            ])
    ]),

2. Создаем чанк core/App/elements/chunks/team.tpl
<section class="team row">
    {foreach $team as $item}
        {*IMAGE*}
        {if $item.type === 'image'}
            <div class="col-12 col-md-6 col-lg-4 mb-4">
                <img
                    loading="lazy"
                    src="{$item.image.url|pthumb:'w=416&h=416&zc=T&f=webp'}"
                    class="img-fluid mb-2"
                    width="416"
                    height="416"
                    alt="{$item.name}">
                <h5>{$item.name}</h5>
                <p>{$item.position}</p>
            </div>
        {/if}

        {*TEXT*}
        {if $item.type === 'text'}
            <div class="col-12 col-md-6 col-lg-4 mb-4">
                <div class="d-flex flex-column align-item-center justify-content-center m-auto h-100 pb-5"
                     style="max-width: 250px">
                    <h2 class="mb-3">{$item.title}</h2>
                    {$item.description}
                </div>
            </div>
        {/if}

        {*VACANCY*}
        {if $item.type === 'vacancy'}
            <div class="col-12 col-md-6 col-lg-8 mb-4">
                <div class="d-flex flex-column align-item-center justify-content-center m-auto h-100 pb-5"
                     style="max-width: 500px">
                    <div class="d-flex flex-column gap-3 align-items-start">
                        <h2>{$item.title}</h2>
                        {$item.description}
                        {$item.button|button}
                    </div>
                </div>
            </div>
        {/if}

    {/foreach}
</section>

Кнопка будет открывать модальное окно с формой, настройка кнопки в админке:


Для генерации кнопки на фронте используется модификатор button, который выводит готовый HTML с нужными атрибутами.

3. Модальное окно с формой
Чанк: core/App/elements/chunks/modal.tpl
<div class="modal fade" id="jobModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header">
                <h1 class="modal-title fs-5">Присоединяйся к команде PageBlocks</h1>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <form action="/form/submit" method="post" data-pbform enctype="multipart/form-data">
                <input type="hidden" name="formname" value="Job">
                <input type="hidden" name="honeypot" value="">
                <input type="hidden" name="_token" value="{csrf_token}">
                <div class="modal-body">
                    <div class="mb-3">
                        <label for="job-name" class="col-form-label">Ваше имя:</label>
                        <input type="text" class="form-control" name="name" id="job-name">
                        <span class="invalid-feedback" data-error="name"></span>
                    </div>
                    <div class="mb-3">
                        <label for="job-email" class="col-form-label">E-mail:</label>
                        <input type="email" class="form-control" name="email" id="job-email">
                        <span class="invalid-feedback" data-error="email"></span>
                    </div>
                    <div class="mb-3">
                        <label for="job-file" class="col-form-label">Резюме (PDF, DOC, DOCX):</label>
                        <input type="file" class="form-control" name="file" id="job-file">
                        <span class="invalid-feedback" data-error="file"></span>
                    </div>
                    <div class="mb-3">
                        <label for="job-message" class="col-form-label">Сопроводительное письмо:</label>
                        <textarea class="form-control" name="message" id="job-message"></ textarea>
                        <span class="invalid-feedback" data-error="message"></span>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
                    <button type="submit" class="btn btn-primary">Отправить резюме</button>
                </div>
            </form>
        </div>
    </div>
</div>
В следующей статьи мы рассмотрим обработку формы 2 способами.

Все, кто дочитал до конца, ставьте лайк!
Aleksandr Huz
17 апреля 2025, 10:27
modx.pro
371
+8
Поблагодарить автора Отправить деньги

Комментарии: 0

Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
0