bigfork/silverstripe-formtacular

安装: 341

依赖者: 1

建议者: 0

安全: 0

星标: 0

关注者: 5

分支: 0

开放问题: 0

类型:silverstripe-vendormodule

0.0.10 2023-08-11 09:31 UTC

This package is auto-updated.

Last update: 2024-09-11 12:49:58 UTC


README

Silverstripe Formtacular

这是一个尝试替换/合并display-logiczenvalidator功能的正在进行中的工作,目的是移除jQuery和jQuery Entwine依赖。

完成

  • 结合条件字段和条件验证功能。
  • 尽可能与display-logic兼容的API(实际上已完全完成)。
  • 无依赖的JavaScript逻辑。
  • 可扩展,例如自定义显示规则。
  • “可插拔”,可以覆盖前端的JavaScript显示规则。
  • CMS兼容性。这已实现功能,但尚未进行广泛测试。

待办事项

  • 此模块不需要作为前端条件验证的一部分,只需配置即可 - 但应该展示如何实现示例。
  • 整理JavaScript API。污染“window”不是理想的选择,但它确实使事情相对简单...
  • 在约束方面与zenvalidator具有相同的功能,利用updateValidationResult扩展钩子(仅适用于SS5)
  • 与用户表单条件显示逻辑兼容

所需CSS

没有提供前端CSS,因为对于99%的使用场景来说这很简单,而且从单独的CSS文件中加载它似乎很浪费,因为它很容易添加到现有项目中

div.formtacular-hidden {
    display: none;
}

如果您条件性地显示/隐藏其他元素,例如HeaderField,您可能需要扩展选择器列表。尽量避免仅使用.formtacular-hidden类选择器(即不使用元素),因为该类将由Silverstripe添加到两者(字段容器div和表单字段本身),因此您的字段可能始终不可见!

快速示例

$fields = FieldList::create(
    TextField::create('FirstName', 'First name'),
    TextField::create('Surname', 'Surname'),
    TextField::create('ContactMethod', 'Contact method', [
        'Email' => 'Email',
        'Telephone' => 'Telephone'
    ]),
    $email = EmailField::create('Email', 'Email'),
    $telephone = TextField::create('Telephone', 'Telephone')
);

$email->displayIf('ContactMethod')->isEqualTo('Email');
$email->validateIfVisible();

$telephone->displayIf('ContactMethod')->isEqualTo('Telephone');
$telephone->validateIfVisible();

// This subclass of RequiredFields is currently necessary
// It may be possible in Silverstripe 5 to remove this by utilising field validation extension hooks
$validator = \Bigfork\SilverstripeFormtacular\Validators\RequiredFields::create([
    'Name',
    'Surname',
    'ContactMethod',
    'Email',
    'Telephone'
])

从display-logic切换

  • 将此模块添加到您的composer要求中,它将自动替换任何依赖或子依赖中的display-logic
  • Wrapper::create()切换到仅使用CompositeField::create()。此步骤可以跳过,因为提供了一个Wrapper类,以尝试使生活更轻松

AJAX表单

根据您处理AJAX表单的方式,您可能需要在提交后重新初始化JavaScript。由于每个方法都不同,您需要根据自己的逻辑来实现表单重新初始化,如果/当HTML被修改。例如,处理AJAX表单提交的一种流行方式是将整个表单HTML替换为来自服务器的响应;因此,您的表单处理程序可以执行类似以下操作

// Your import path may vary
import FormtacularForm from '~vendor/bigfork/silverstripe-formtacular/client/src/js/classes/FormtacularForm';

.then((response) => {
  const formHTML = response;
  let $form = $container.find('form');

  const forms = window['formtacular_forms'];
  forms.remove($form.get(0));

  $form.replaceWith(formHTML);
  $form = $container.find('form'); // Re-fetch to get new <form>

  const formtacularForm = new FormtacularForm($form.get(0));
  forms.set(node, form);
});

处理此问题的另一种“全局”方法是使用MutationObserver来检测任何表单被添加到或从文档中删除

// Your import path may vary
import FormtacularForm from '~vendor/bigfork/silverstripe-formtacular/client/src/js/classes/FormtacularForm';

const observer = new MutationObserver((mutations) => {
  const forms = window['formtacular_forms'];
  
  mutations.forEach((mutation) => {
    [...mutation.removedNodes].forEach((node) => {
      if (node.nodeName === 'FORM') {
        forms.remove(node);
      }
    });

    [...mutation.addedNodes].forEach((node) => {
      if (node.nodeName === 'FORM') {
        if (!node.hasAttribute('data-formtacular-visibility')) {
          return;
        }

        const form = new FormtacularForm(node);
        forms.set(node, form);
      }
    });
  });
});

addEventListener('DOMContentLoaded', () => {
  observer.observe(document.body, { childList: true, subtree: true });
});

自定义

如果您需要更改字段值的获取方式或绑定事件的方式,例如如果您正在使用JavaScript库来装饰表单字段,您可以通过覆盖注册在window上的全局函数来实现。例如,在此模块的CMS包中,由于jQuery可用,我们利用它来获取字段值

window['formtacular_bindChangeEvent'] = (input, handler) => {
    $(input).on('change input', handler);
};

请查看client/src/js/rulesclient/src/js/utils目录中的源JavaScript,以获取可以覆盖的函数的完整列表以及何时希望这样做。

添加检查/规则

您可以通过扩展Bigfork\SilverstripeFormtacular\Rules\AbstractRule、在YAML中注册它并编写相应的JavaScript函数来编写自己的检查。

<?php

use Bigfork\SilverstripeFormtacular\Rules\AbstractRule;

class IsStringLongerThanRule extends AbstractRule
{
    protected int $length;

    public function __construct(string $fieldName, int $length)
    {
        $this->length = $length;
        parent::__construct($fieldName);
    }

    public function getResult(): bool
    {
        return strlen($this->getFormField()->dataValue()) > $this->length;
    }

    public function getJavaScriptTestName(): string
    {
        return 'evaluateIsStringLongerThan';
    }

    public function getJavaScriptTestArguments(): array
    {
        return [$this->length];
    }
}

// ...

$field = TextField::create('TestField', 'Test field');
$field->displayIf('AnotherTestField')->isStringLongerThan(5);
Bigfork\SilverstripeFormtacular\Rules\RuleSet:
  fluid_syntax_rules:
    isStringLongerThan: 'IsStringLongerThanRule'
window['formtacular_evaluateIsStringLongerThan'] = (form, config) => {
    const value = window.formtacular_getFieldValue(form, config);
    return typeof value === 'string' && value.length > config.arguments[0];
}