Создание бизнес-сайта с любой CMS требует, чтобы вы сделали бэк-энд дружественным к пользователю, а это означает, что формы должны быть осмысленными и доступными В этой статье мы рассмотрим виджеты формы UniqueValue
и создадим виджет с именем UniqueValue
, который поможет пользователю ввести уникальное значение. Это может быть полезно для ввода электронных писем, имен пользователей, почтовых слагов и т. Д. Давайте начнем.
Доступные виджеты формы
OctoberCMS предоставляет список простых типов полей, таких как ввод электронной почты, пароль, параметры раскрывающегося списка и т. Д. В документации есть список всех доступных полей. Кроме того, CMS предоставляет несколько пользовательских виджетов, таких как виджет менеджера мультимедиа, который позволяет вам выбирать элемент из вашей медиатеки или редактора WYSIWYG, редактора Markdown и т. Д.
Интересный виджет, о котором следует упомянуть, это виджет повторителя . Допустим, у вас есть сайт рецептов. Повар введет название рецепта и начнет заполнять ингредиенты. Вы можете спросить пользователя «сколько ингредиентов вам нужно?» И на основе этого вы можете создать поля формы. Еще один простой способ сделать это — кнопка внизу формы с надписью « Add new ingredient
, которая при необходимости создаст необходимые поля для повара.
Вот пример конфигурации для формы рецепта:
// models/recipe/fields.yaml fields : name : label : Name type : text required : true ingredients : label : Ingredients type : repeater prompt : Add new ingredient form : fields : ingredient : label : Ingredient type : text how_much : label : How much type : number unit : label : Unit type : dropdown options : spoon : Spoon ounce : Ounce # etc
Создание виджета формы
Если вы прочитаете предыдущую статью OctoberCMS (вы должны, это здорово!), Вы будете знать, что мы создали плагин CRUD . Мы будем использовать его в этой статье, поэтому обязательно клонируйте его в вашу установку OctoberCMS.
# Inside your plugins folder git clone git @github . com : Whyounes / OctoberCMS_Sitepoint_plugin_demo . git rafie / sitepointDemo
Вы можете проверить окончательный код этого урока в uniqueValue-formwidget
в том же репо .
Чтобы начать создание нашего виджета, мы используем create:formwidget
scaffolding create:formwidget
которая создает папку представлений, папку активов и класс FormWidgetBase
.
php artisan create : formwidget rafie . SitepointDemo UniqueValue
Наш виджет UniqueValue
требует трех свойств:
-
modelClass
: класс модели, который будет иметь уникальное поле. -
selectFrom
: имя поля внутри модели. По умолчаниюname
. -
pattern
: отображаемый тип ввода (text
,email
,number
,url
). По умолчаниюtext
.
После того, как наш класс виджета формы создан, он автоматически вызовет унаследованный метод init
, который отвечает за подготовку нашего виджета к визуализации.
// formwidgets/UniqueValue.php class UniqueValue extends FormWidgetBase { /** * {@inheritDoc} */ protected $defaultAlias = 'rafie_sitepointDemo_uniquevalue' ; /** * {@inheritDoc} */ public function init ( ) { } }
Наш родительский класс WidgetBase
предоставляет вспомогательный метод fillFromConfig
который отображает переданные свойства конфигурации из файла fields.yaml
в атрибуты класса виджета формы.
// formwidgets/UniqueValue.php class UniqueValue extends FormWidgetBase { /* * Config attributes */ protected $modelClass = null ; protected $selectFrom = 'name' ; protected $pattern = 'text' ; /** * {@inheritDoc} */ protected $defaultAlias = 'rafie_sitepointDemo_uniquevalue' ; /** * {@inheritDoc} */ public function init ( ) { $this - > fillFromConfig ( [ 'modelClass' , 'selectFrom' , 'pattern' ] ) ; $this - > assertModelClass ( ) ; parent : : init ( ) ; } // ... }
После вызова функции fillFromConfig
мы утверждаем, что класс модели существует, а затем вызываем родительский метод init
.
// formwidgets/UniqueValue.php class UniqueValue extends FormWidgetBase { // ... protected function assertModelClass ( ) { if ( ! isset ( $this - > modelClass ) || ! class_exists ( $this - > modelClass ) ) { throw new \ InvalidArgumentException ( sprintf ( "Model class {%s} not found." , $this - > modelClass ) ) ; } } // ... }
// formwidgets/uniquevalue/UniqueValue.php class UniqueValue extends FormWidgetBase { // ... public function render ( ) { $this - > prepareVars ( ) ; return $this - > makePartial ( 'uniquevalue' ) ; } /** * Prepares the form widget view data */ public function prepareVars ( ) { $this - > vars [ 'inputType' ] = $this - > pattern ; $this - > vars [ 'name' ] = $this - > formField - > getName ( ) ; $this - > vars [ 'value' ] = $this - > getLoadValue ( ) ; $this - > vars [ 'model' ] = $this - > model ; } }
OctoberCMS будет искать частичное внутри папки partials
и передавать $this->vars
массив $this->vars
.
// formwidgets/uniquevalue/partials/_uniquevalue.htm <?php if ($this->previewMode): ?> < div class = " form-control " > <?= $value ?> </ div > <?php else: ?> < div class = " input-group " > <input type=" <?= $inputType ?> " id=" <?= $this->getId('input') ?> " name=" <?= $name ?> " value=" <?= $value ?> " class="form-control unique_widget" autocomplete="off" /> < span class = " input-group-addon oc-icon-remove " > </ span > </ div > <?php endif ?>
Вход имеет предварительный просмотр и режим редактирования. При редактировании мы отображаем ввод и заполняем тип, используя указанный шаблон. В этом случае значение устанавливается автоматически, если мы обновляем запись. Элемент span.input-group-addon
будет отображать флажок или значок удаления в зависимости от введенного значения.
Использование AJAX
OcotberCMS имеет набор сценариев, которые позволяют обновлять содержимое с помощью атрибутов данных HTML5 и обработчиков AJAX. Мы можем подробно рассказать об этом в другой статье, но вы можете обратиться к документации для получения более подробной информации прямо сейчас, если вам интересно.
Мы собираемся проверить, является ли введенное значение уникальным при изменении входного значения. Сначала нам нужно добавить атрибут data-request
который указывает имя обработчика метода бэкэнда.
// formwidgets/uniquevalue/partials/_uniquevalue.htm // ... <input type=" <?= $inputType ?> " id=" <?= $this->getId('input') ?> " name=" <?= $name ?> " value=" <?= $value ?> " class="form-control unique_widget" autocomplete="off" data-request="onChange" /> // ...
Далее мы указываем функцию JS, которая будет обрабатывать ответ успешного запроса, используя атрибут data-request-success
. Он получит список параметров, но наиболее важными из них являются $el
, который относится к нашему вводу, и параметр data
, который содержит результат запроса.
// formwidgets/uniquevalue/partials/_uniquevalue.htm // ... <input type=" <?= $inputType ?> " id=" <?= $this->getId('input') ?> " name=" <?= $name ?> " value=" <?= $value ?> " class="form-control unique_widget" autocomplete="off" data-request="onChange" data-request-success="uniqueInputChanged($el, context, data, textStatus, jqXHR);" /> // ...
AJAX-инфраструктура OctoberCMS предоставляет атрибут data-track-input
для запуска обработчика data-request
если элемент изменился. Он принимает необязательный параметр задержки, который мы можем использовать, чтобы минимизировать количество отправленных запросов.
// formwidgets/uniquevalue/partials/_uniquevalue.htm // ... <input type=" <?= $inputType ?> " id=" <?= $this->getId('input') ?> " name=" <?= $name ?> " value=" <?= $value ?> " class="form-control unique_widget" autocomplete="off" data-request="onChange" data-request-success="uniqueInputChanged($el, context, data, textStatus, jqXHR);" data-track-input="500" /> // ...
Мы все еще не определили наш onChange
обработчика onChange
внутри нашего класса виджетов формы. OctoberCMS будет искать обработчик с тем же именем внутри контроллера внутренней страницы или любых других используемых виджетов. Чтобы избежать конфликтов, мы используем имя обработчика с префиксом, которое будет содержать псевдоним нашего виджета.
// formwidgets/uniquevalue/partials/_uniquevalue.htm // ... <input // ... data-request=" <?= $this->getEventHandler('onChange') ?> " // ... /> // ...
// formwidgets/uniquevalue/UniqueValue.php class UniqueValue extends FormWidgetBase { // ... public function onChange ( ) { $formFieldValue = post ( $this - > formField - > getName ( ) ) ; $modelRecords = $this - > model - > newQuery ( ) - > where ( $this - > selectFrom , $formFieldValue ) ; return [ 'exists' = > ( boolean ) $modelRecords - > count ( ) ] ; } // ... }
$this->formField->getName()
возвращает имя ввода, которое мы используем для получения значения ввода из данных публикации. Затем мы вызываем метод modelClass::where
со selectFrom
конфигурации selectFrom
и данными публикации.
Осталось только обработать результат запроса с помощью функции JavaScript, определенной в нашем атрибуте data-request-success
. Наши CSS и JavaScript-ресурсы загружаются внутри UniqueValue@loadAsserts
.
// formwidgets/uniquevalue/UniqueValue.php class UniqueValue extends FormWidgetBase { // ... public function loadAssets ( ) { // $this->addCss('css/uniquevalue.css', 'rafie.SitepointDemo'); $this - > addJs ( 'js/uniquevalue.js' , 'rafie.SitepointDemo' ) ; } // ... }
// formwidgets/uniquevalue/assets/js/uniquevalue.js function uniqueInputChanged ( $el , context , data , textStatus , jqXHR ) { var addon = $el . parents ( '.input-group' ) . find ( '.input-group-addon' ) ; if ( ! $el . val ( ) . trim ( ) || data . exists ) { addon . removeClass ( 'oc-icon-check' ) . addClass ( 'oc-icon-remove' ) ; return ; } addon . removeClass ( 'oc-icon-remove' ) . addClass ( 'oc-icon-check' ) ; }
Мы запрашиваем наш элемент addon, проверяем возвращаемое значение и устанавливаем соответствующий класс значка для элемента. Вы можете проверить виджет, вставив приведенный ниже код в файл конфигурации полей модели.
// fields.yaml fields : slug : label : Slug type : \Rafie\SitepointDemo\FormWidgets\UniqueValue modelClass : \RainLab\Blog\Models\Post selectFrom : slug pattern : text
Это последняя демонстрация виджета.
В качестве последнего шага мы зарегистрируем наш виджет формы как системный виджет ( text
, checkboxlist
и т. Д.).
// Plugin.php // ... /** * Registers any form widgets implemented in this plugin. */ public function registerFormWidgets ( ) { return [ 'Rafie\SitepointDemo\FormWidgets\UniqueValue' = > [ 'label' = > 'Unique Value' , 'code' = > 'uniquevalue' ] , ] ; } // ...
Теперь мы можем использовать наш виджет, используя зарегистрированный код.
// fields.yaml fields : slug : label : Slug type : uniquevalue modelClass : \RainLab\Blog\Models\Post selectFrom : slug pattern : text
Вывод
В этой статье мы исследовали виджеты полей формы OcotberCMS и создали простой демонстрационный виджет для его тестирования. Вы можете расширить конечный виджет, добавив новую функциональность, например, добавив параметр preventSubmit
когда значение не является уникальным, и т. Д. Вы можете проверить окончательную версию на Github, и если у вас есть какие-либо вопросы или комментарии, вы можете оставить их ниже, и я буду сделать все возможное, чтобы ответить на них.