bigfork / silverstripe-formtacular
Requires
- silverstripe/framework: ^4.12|^5
Replaces
README
Silverstripe Formtacular
这是一个尝试替换/合并display-logic和zenvalidator功能的正在进行中的工作,目的是移除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/rules
和client/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]; }