В этом уроке хотел бы совсем немного поговорить про repeater-поля (Complex fields) в плагине Carbon Fields и показать вам пару примеров.
Уже две недели я выхваливаю этот плагин, конечно же только потому что он мне понравился, я ни с кем не партнёрился.
Также не забывайте прочекать мой видеокурс по созданию темы WordPress на основе готовой вёрстки.
Давайте я наверное сначала покажу вам пример, как это выглядит в админке:
На фото выше вы можете заметить, что мы можем добавлять какое-то количество блоков, причём разного типа (с текстом, с фото и с текстом и ссылкой), кроме того их можно менять местами.
Подобное поле на клиентском сайте используется для вывода вот этих блоков:
В самом конце урока вы найдёте видео, в котором я пошагово создавал эти блоки.
Вообще в самом плагине Carbon Fields это поле называется Complex, но все уже привыкли к названию repeater или повторяющиеся поля, потому что оно более подробно описывать, о чём вообще всё это.
Вот супер-лёгкий пример создания повторяющего поля:
Field::make( 'complex', 'truemisha_slider', 'Слайдер' ) ->add_fields( array( Field::make( 'text', 'title', 'Заголовок слайда' ), Field::make( 'image', 'photo', 'Изображение слайда' ), ) ),
И не забываем про хук carbon_fields_register_fields
и в самом начале кода в файле вызвать:
use Carbon_Fields\Container; use Carbon_Fields\Field;
Если вы забываете об этом, то рекомендую вернуться к вступительному уроку про Carbon Fields.
После вставки его в код, у вас появится:
Окей, поля в админке есть, как теперь получить их значения? Помните в руководстве по Carbon Fields я говорил, что не для всех типов полей можно спокойно использовать get_post_meta() ? Вот complex field это как раз и есть такое поля. Поэтому мы будем использовать carbon_get_post_meta()
ну или ту функцию, которая предназначена для настроек таксономий, опций и так далее, в зависимости от того, где вы создаёте поля.
$slides = carbon_get_post_meta( get_the_ID(), 'truemisha_slider' ); if( $slides ) { foreach( $slides as $slide ) { // смысла в слайде ведь нет, если не используется фото?? if( ! $slide[ 'photo' ] ) { continue; // скипаем итерацию цикла, если нет фотки } echo '<div class="slide">'; echo wp_get_attachment_image( $slide[ 'photo' ] ); if( $slide[ 'title' ] ) { // empty() и isset() нет нужды использовать тут echo '<h2>' . esc_html( $slide[ 'title' ] ) . '</h2>'; } echo '</div>' } }
Код очень примерный, но я тем не менее старался сделать его максимально подробным, чтобы вы не забывали учитывать «проверки на дурака», например когда пользователь сайта не заполнил фотку или решил поразвлекаться с HTML-тегами внутри заголовка слайда.
Если вы взглянете на поля настроек нашего слайдера, то заметите, что поле заголовка какой-то невероятной длины, я поле изображения едва ли занимает 1/4 часть от экрана!
Хорошая новость – мы можем задавать ширину полей в процентах (работает на flex-basis
). Например у нас тут с вами два поля, причём для изображения нужно совсем немного места, я думаю 25% будет ок, а остальное можно оставить для заголовка. Но я попробовал такой вариант и решил разделить поля 50 на 50, так оказалось красивее, для этого я использовал метод set_width()
.
Field::make( 'complex', 'truemisha_slider', 'Слайдер' ) ->add_fields( array( Field::make( 'text', 'title', 'Заголовок слайда' )->set_width( 50 ), Field::make( 'image', 'photo', 'Изображение слайда' )->set_width( 50 ), ) ),
И вот результат:
Хорошо, идём апгрейдить наш слайдер дальше – что если там будет не только фото, но и видео! Причём в любом порядке!
Тут на самом деле всё легко, чтобы в один репитер добавлять разные группы, мы всего лишь снова и снова используем метод add_fields()
.
Field::make( 'complex', 'truemisha_slider', 'Слайдер' ) ->add_fields( 'image', 'Изображение', array( Field::make( 'text', 'title', 'Заголовок слайда' ), Field::make( 'image', 'photo', 'Изображение слайда' ), ) ) ->add_fields( 'movie', 'Видос', array( Field::make( 'text', 'title', 'Заголовок слайда' ), Field::make( 'file', 'video', 'Видео слайда' ), ) ),
На скриншоте ниже понятно, что при нажатии на кнопку добавления группы, вы можете выбрать, какая это будет группа – с фото или с видео:
Ах да, когда будете выводить такое поле на сайте, то у каждого слайда появится параметр типа, а именно $slide[ '_type' ]
, который будет равен или image
или movie
.
Возможно вы не захотите, чтобы поля шли друг за другом вертикально, тогда хочу предложить вам ещё две опции – это отображение полей в виде горизонтальных и вертикальных вкладок, для этого мы будем использовать метод set_layout() непосредственно к комплексному полю.
Например:
Field::make( 'complex', 'truemisha_slider', 'Слайдер' )->set_layout( 'tabbed-horizontal' )
Получается:
Или например:
Field::make( 'complex', 'truemisha_slider', 'Слайдер' )->set_layout( 'tabbed-vertical' )
Получается:
Да – внутри репитера может быть ещё один репитер! 🤯
Ну и это прекрасно, я думаю. Правда я не знаю, как это можно применить к нашему примеру слайдера. Давайте сделаем как в официальной документации – заменим поле заголовка на репитер, т е возможность добавлять несколько текстовых элементов.
Field::make( 'complex', 'truemisha_slider', 'Слайдер' ) ->add_fields( array( Field::make( 'image', 'photo', 'Изображение слайда' ), Field::make( 'complex', 'slide_fragments', 'Надписи на слайде' ) ->add_fields( array( Field::make( 'text', 'fragment_text', 'Текст' ), Field::make( 'select', 'fragment_position', 'Расположение' ) ->add_options( array( 'Сверху слева', 'Сверху справа', 'Снизу слева', 'Снизу справа' ) ), )) )),
Ну и в админке это будет выглядеть вот так:
Тут легко – допустим мы не хотим, чтобы пользователи сайта добавляли сотни слайдов, которые естественно отразятся на скорости загрузки страниц, поэтому установим предел этому:
Field::make( 'complex', 'truemisha_slider', 'Слайдер' )->set_max( 5 ) // 5 слайдов это уже норм!
Это будет работать таким образом, что при добавлении 5-го слайда, кнопка добавления повторения поля будет исчезать – удобно!
У каждой повторяющейся группы полей рядом с кнопкой удаления есть кнопка дублирования группы:
Эту кнопку можно отключить методом set_duplicate_groups_allowed()
.
Field::make( 'complex', 'truemisha_slider', 'Слайдер' )->set_duplicate_groups_allowed( false )
Выше в примерах вы уже могли заметить, что я добавлял заголовки группам, но это были очень примитивные заголовки типо «Изображение» или «Видео», но самое интересное начинается тогда, когда к этим заголовкам мы можем добавлять ещё и значение одного из поля внутри группы!
Например использовав метод set_header_template()
и вот такой код:
Field::make( 'complex', 'truemisha_slider', 'Слайдер' ) ->add_fields( 'image', 'Изображение', array( Field::make( 'text', 'title', 'Заголовок слайда' ), Field::make( 'image', 'photo', 'Изображение слайда' ), ) ) ->set_header_template( ' <% if (title) { %> Изображение: <%- title %> % } %> ' ) ->add_fields( 'movie', 'Видос', array( Field::make( 'text', 'title', 'Заголовок слайда' ), Field::make( 'file', 'video', 'Видео слайда' ), ) ) ->set_header_template( ' <% if (title) { %> Видос: <%- title %> <% } %> ' ),
Мы получим очень классный результат:
Пример при ипользовании двух значений полей внутри заголовка:
->set_header_template( ' <% if (name) { %> Пассажир: <%- name %> <%- years ? "(" + years + ")" : "" %> <% } %> ' )
Чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или войдите.
Здравия, Миша. Пишешь и рассказываешь ты от души: щедро и понятно. Спасибо!
У меня есть 2 вопроса-задачи:
1) Можно ли запретить пользователю перетаскивание полей мышкой?
2) Можно ли сделать присвоение значения поля по умолчанию переменным (разным) для каждого нового экземпляра поля? Например в каждое новое поле, создаваемое пользователем, писать по умолчанию номер строки (индекс поля) или случайное число.
Подскажи, пожалуйста, как можно сделать эти 2 задачи?
Привет! Спасибо!
1) С этим не сталкивался к сожалению, поэтому код не подскажу
2) Тут я думаю можно заюзать метод
Field::make(...)->set_default_value( $default_value )
Спасибо!
Запрет перетаскивания полей сделал так.
"Перетаскивание" полей привязано к классу CSS .cf-complex__group-head
Возникла идея: заменить этот класс другим.
Для этого:
а) создал новый класс, куда скопировал нужные свойства из класса .cf-complex__group-head
б) для страницы редактирования в футер добавил скрипт замены одного класса на другой по хуку admin_print_footer_scripts.
Вроде у меня работает так как надо. Удачи
Спасибо, что поделились кодом!
Приветствую Миша, как выводить из поля comlex поле media_gallery
спасибо)
Приветствую! Михаил вы не сталкивались с тем, что некоторым поля нужно задать значение по умолчанию, которые мы берем уже с существующего поля. Самый просто вариант это взять нужные посты через get_posts и для каждого отдельного поста добавить Container::make (чтобы была возможность получить поле), вот я о чем:
Сталкивались ли вы с таким и есть ли для этого более изящный способ, чем добавлять cf поля через цикл? Может быть вопросов бы и не возникло, если бы не было задачи задавать поля внутри комплексного поля (комплекс_2), которое внутри комплексного (комплекс_1) поля и для поля в группе полей комплекс_2 нужно задать значение по умолчанию, используя поле из группы полей комплекс_1, грубо говоря из родительской группы полей, вот пример кода для лучшего понимания: