我有一个很大的实体和一个大的形式.更新我的实体时,我只通过ajax调用渲染表单的一部分.在客户端,我使用Jquery和html5 FormData,所以我也可以在我的表单中发送文件.为了确保在进程中未呈现的字段不会设置为null,我正在使用PATCH方法.
因此,当请求中不存在某个字段时,Symfony 就会保留该字段.
但是当我更新的字段是一个设置为true的布尔值(呈现的aa复选框)并且我想将其设置为false时,它不会在请求中传递,因此我的更新被忽略.
是否有一种简单的方法可以强制取消选中复选框以显示在请求中?
编辑
我找到了一种强制未选中复选框出现在请求中的方法,这要感谢Felix Kling对此问题的评论:
$("input:checkbox:not(:checked)").each(function() {
formData.set($(this).attr('name'), formData.has($(this).attr('id')) ? '1' : '0');
});
Run Code Online (Sandbox Code Playgroud)
不幸的是,由于Symfony的行为,这并没有解决我的问题:
- 当使用PUT时,如果请求中出现布尔字段,则无论其值如何(即使它为"0"或"false"),它都设置为true .
- 使用PATCH方法时,将忽略请求中未出现的字段.
可以用DataTransformer解决吗?(我从来没用过它)
完全正确,如果方法是PATCH,Symfony将忽略它,因为Request Handler中的这一行:
$form->submit($data, 'PATCH' !== $method);
Run Code Online (Sandbox Code Playgroud)
现在,我通常会建议您使用PUT请求(如果可以选择的话),但是如果不是,那么FormInterface::submit($submittedData, $clearMissing = true)您要使用的第二个参数。
“正确”的方式很可能是使自己实现Symfony\Component\Form\RequestHandlerInterface这将迫使$clearMissing是true。
另外,方法要容易得多,但可能不适用于所有用例:$form->submit()直接使用。
如果您具有以下代码:
$form->handleRequest($request);
Run Code Online (Sandbox Code Playgroud)
你可以做:
$form->submit($request->get($form->getName()), true);
Run Code Online (Sandbox Code Playgroud)
您也可以省略第二个参数,因为true它是默认值
这是一个可行的解决方案,可以改进。
为了强制未选中的复选框出现在请求中,感谢 Felix Kling 对这个问题的评论,我在 ajax 请求之前添加了这个 js :
$("input:checkbox:not(:checked)").each(function() {
formData.set($(this).attr('name'), formData.has($(this).attr('id')) ? '1' : '0');
});
Run Code Online (Sandbox Code Playgroud)
然后,在 Symfony 方面,我必须重写 BooleanToStringTransformer 行为,该行为返回true任何字符串且false仅返回 null 值。对最后一行进行更改,如果该值与为true定义的值(默认为“1”)不匹配,我们现在返回false 。因此,如果表单返回的值为“0”,我们将得到false,正如预期的那样。
public function reverseTransform($value)
{
if (null === $value) {
return false;
}
if (!is_string($value)) {
throw new TransformationFailedException('Expected a string.');
}
return ($this->trueValue === $value); // initially: "return true;"
}
Run Code Online (Sandbox Code Playgroud)
按照文档,我制作了自己的 DataTransformer 以及自定义AjaxCheckboxType
不幸的是,Symfony 似乎同时使用了两个DataTransformers(我的和原来的),一个接一个,所以它不起作用。TextType在他们扩展的文档中CheckboxType,这必须解释我遇到的问题。
我最终将整个内容复制并粘贴CheckboxType class到我自己的 AjaxCheckboxType 中,仅更改 DataTransformer 的调用才能使用我的。
一个更好的解决方案是完全覆盖 DataTransformer,但我不知道如何。
| 归档时间: |
|
| 查看次数: |
1617 次 |
| 最近记录: |