隐藏表单字段_像Pro一样构建OctoberCMS表单字段小部件

隐藏表单字段

OctoberCMS logo

Creating your business website with any CMS requires you to make the back-end user friendly, and that means making the forms meaningful and accessible. In this article, we’re going to explore OctoberCMS form widgets and create a widget called UniqueValue, which helps the user enter a unique value. This could be useful for entering emails, usernames, post slugs, etc. Let’s get started.

使用任何CMS创建业务网站都需要使后端用户友好,这意味着使表格有意义且易于访问。 在本文中,我们将探索OctoberCMS表单小部件,并创建一个名为UniqueValue小部件,该小部件可帮助用户输入唯一值。 这对于输入电子邮件,用户名,帖子内容等很有用。让我们开始吧。

可用的表单小部件 (Available Form Widgets)

OctoberCMS provides a list of simple field types like email input, password, dropdown options, etc. The documentation has a list of all available fields. Moreover, the CMS provides some custom widgets like the media manager widget which lets you select an item from your media library or the WYSIWYG editor, Markdown editor, etc.

OctoberCMS提供了简单字段类型的列表,例如电子邮件输入,密码,下拉选项等。 文档中包含所有可用字段的列表。 此外,CMS还提供了一些自定义小部件,例如媒体管理器小部件,可让您从媒体库或WYSIWYG编辑器,Markdown编辑器等中选择一个项目。

An interesting widget we should mention here is the repeater widget. Let’s say you have a recipes website. The cook will enter the recipe name and start filling in the ingredients. You might ask the user “how many ingredients do you need?” and based on that, you can generate the form fields. Another clean way to do it is to have a button at the bottom of the form that says Add new ingredient, which will generate the necessary fields for the cook when needed.

我们应该在这里提到的一个有趣的小部件是转发器小部件 。 假设您有一个食谱网站。 厨师将输入食谱名称,并开始填写食材。 您可能会问用户“您需要多少成分?” 基于此,您可以生成表单字段。 另一种干净的方法是在表格底部有一个按钮,上面写着Add new ingredient ,它将在需要时为厨师生成必要的字段。

Here is an example configuration for the recipe form:

这是配方表格的示例配置:

// 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
ingredients

创建一个表单小部件 (Creating a Form Widget)

If you read the previous OctoberCMS article (you should, it’s great!), you’ll know that we built a CRUD plugin. We’ll be using it in this article, so make sure to clone it into your OctoberCMS installation.

如果您阅读了上一篇OctoberCMS的文章 (您应该很棒,那太好了!),您会知道我们构建了一个CRUD插件 。 我们将在本文中使用它,因此请确保将其克隆到OctoberCMS安装中。

# Inside your plugins folder

git clone git@github.com:Whyounes/OctoberCMS_Sitepoint_plugin_demo.git rafie/sitepointDemo

You can check the final code for this tutorial in the uniqueValue-formwidget branch in the same repo.

您可以检查最终代码本教程中uniqueValue-formwidget分支在同一回购

To start building our widget, we use the create:formwidget scaffolding command which creates a view folder, assets folder and a FormWidgetBase class.

要开始构建窗口小部件,我们使用create:formwidget脚手架命令,该命令将创建视图文件夹,资产文件夹和FormWidgetBase类。

php artisan create:formwidget rafie.SitepointDemo UniqueValue

Our UniqueValue widget requires three properties:

我们的UniqueValue小部件需要三个属性:

  • modelClass: The model class that will have the unique field.

    modelClass :将具有唯一字段的模型类。

  • selectFrom: The field name inside the model. Defaults to name.

    selectFrom :模型内的字段名称。 默认为name

  • pattern: The displayed input type (text, email, number, url). Defaults to text.

    pattern :显示的输入类型( textemailnumberurl )。 默认为text

After our form widget class is constructed, it will automatically call the inherited init method, which is responsible for preparing our widget for rendering.

构造窗体小部件类后,它将自动调用继承的init方法,该方法负责准备要渲染的小部件。

// formwidgets/UniqueValue.php

class UniqueValue extends FormWidgetBase
{
    /**
     * {@inheritDoc}
     */
    protected $defaultAlias = 'rafie_sitepointDemo_uniquevalue';

    /**
     * {@inheritDoc}
     */
    public function init()
    {
    }
}

Our parent WidgetBase class provides a fillFromConfig helper method which maps the passed config properties from the fields.yaml file to the form widget class’ attributes.

我们的父WidgetBase类提供了fillFromConfig帮助器方法,该方法将传递的config属性从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();
    }
    
    // ...
}

After calling the fillFromConfig function, we assert that the model class exists and then call the parent init method.

调用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 will look for the partial inside the partials folder and pass the $this->vars array to it.

OctoberCMS将在partials文件夹中查找partial,然后将$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 ?>

The input has a preview and an editing mode. When editing, we display an input and fill the type using the specified pattern. The value is automatically set in this case if we are updating a record. The span.input-group-addon element will display a check or a remove icon depending on the entered value.

输入具有预览和编辑模式。 在编辑时,我们显示输入并使用指定的模式填充类型。 如果我们要更新记录,则在这种情况下将自动设置该值。 span.input-group-addon元素将根据输入的值显示选中删除图标。

使用AJAX (Using AJAX)

OcotberCMS has a set of scripts that let you update your content using HTML5 data attributes and AJAX handlers. We may cover it in detail in another article, but you can refer to the documentation for more details right now, if you’re curious.

OcotberCMS具有一组脚本,使您可以使用HTML5数据属性和AJAX处理程序来更新内容。 我们可能会在另一篇文章中对其进行详细介绍,但是如果您感到好奇,可以立即参考文档以获取更多详细信息。

We’re going to check if the entered value is unique when the input value changes. First we need to add the data-request attribute which specifies the backend method handler name.

当输入值更改时,我们将检查输入值是否唯一。 首先,我们需要添加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"
        />
// ...

Next, we specify the JS function that will handle a successful request’s response using the data-request-success attribute. It will receive a list of parameters, but the most important ones are $el, which refers to our input, and the data parameter, which holds the request’s result.

接下来,我们使用data-request-success属性指定JS函数来处理成功请求的响应。 它会收到一个参数列表,但是最重要的是$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);"
        />
// ...

OctoberCMS’ AJAX framework provides a data-track-input attribute to trigger the data-request handler if the element has changed. It accepts an optional delay parameter which we can use to minimize the number of sent requests.

OctoberCMS的AJAX框架提供了data-track-input属性,以在元素发生更改时触发data-request处理程序。 它接受一个可选的delay参数,我们可以使用该参数来最小化已发送请求的数量。

// 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"
        />
// ...

We still didn’t define our onChange handler method inside our form widget class. OctoberCMS will look for a handler with the same name inside the backend page controller or any other widgets used. To avoid conflicts, we use the fully prefixed handler name which will include our widget alias.

我们仍然没有在表单小部件类中定义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() returns the input name that we use to get the input value from the post data. Then, we call the modelClass::where method with the selectFrom config value and the post data.

$this->formField->getName()返回我们用来从发布数据中获取输入值的输入名称。 然后,我们使用selectFrom config值和post数据调用modelClass::where方法。

The only thing left is to process the request’s result using the JavaScript function defined in our data-request-success attribute. Our CSS and JavaScript assets are loaded inside the UniqueValue@loadAsserts method.

剩下的唯一事情就是使用我们在data-request-success属性中定义JavaScript函数处理请求的结果。 我们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');
}

We query our addon element, test the return value, and set the appropriate icon class on the element. You can test the widget by inserting the below code inside your model fields configuration file.

我们查询addon元素,测试返回值,并在该元素上设置适当的图标类。 您可以通过在模型字段配置文件中插入以下代码来测试窗口小部件。

// fields.yaml

fields:
    slug:
        label: Slug
        type: \Rafie\SitepointDemo\FormWidgets\UniqueValue
        modelClass: \RainLab\Blog\Models\Post
        selectFrom: slug
        pattern: text

This is a final demo of the widget.

这是小部件的最终演示。

Test UniqueValue Form Widget

As a final step, we will register our form widget as a system widget (text, checkboxlist, etc).

最后一步,我们将表单小部件注册为系统小部件( textcheckboxlist等)。

// Plugin.php

// ...
/**
 * Registers any form widgets implemented in this plugin.
 */
public function registerFormWidgets()
{
    return [
        'Rafie\SitepointDemo\FormWidgets\UniqueValue' => [
            'label' => 'Unique Value',
            'code' => 'uniquevalue'
        ],
    ];
}
// ...

Now, we can use our widget by using the registered code.

现在,我们可以使用注册的代码来使用小部件。

// fields.yaml

fields:
    slug:
        label: Slug
        type: uniquevalue
        modelClass: \RainLab\Blog\Models\Post
        selectFrom: slug
        pattern: text

结论 (Conclusion)

In this article, we explored the OcotberCMS backend form field widgets and we built a simple demo widget to test it. You can extend the final widget by adding new functionality, like adding a preventSubmit option when the value is not unique, etc. You can check the final version on Github and if you have any questions or comments you can leave them below and I’ll do my best to answer them.

在本文中,我们探索了OcotberCMS后端表单字段小部件,并构建了一个简单的演示小部件对其进行测试。 您可以通过添加新功能来扩展最终的小部件,例如在值不唯一时添加preventSubmit选项等。您可以在Github上检查最终版本,如果有任何疑问或意见,可以将其保留在下面,我将尽我所能回答他们。

翻译自: https://www.sitepoint.com/building-octobercms-form-field-widgets-like-a-pro/

隐藏表单字段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值