在我的应用程序中,我有几个表单字段,有很多选项。我遇到的问题类似于this question:在每个页面加载时获取和解析所有选项都很昂贵(Twig一遍又一遍地渲染所有选项,而没有客户端缓存可能)。这个问题让我创建了一种通过AJAX将选项发送到浏览器的方法。相当简单的方法:
为防止Symfony查询所有选项(不必要:他们通过AJAX加载)我在加载表单时将setMaxResults(0)
添加到QueryBuilder
(通过控制器添加选项) )。是的,这就是kludge。提交表单时,它仍会执行查询,因为它必须验证所选选项是否存在(并检查约束)。
我想创建一个custom Form Field Type,将此功能添加到当前EntityType
:在呈现表单时不加载选项,但仍检查所选选项是否存在。我发现many examples与dynamically modifying a form有关,但我找不到与修改一个表单字段相关的示例,而与其父表单无关。
如何创建这样的表单字段类型?什么是一个很好的起点?扩展EntityType
,ChoiceType
还是其他方法?
我已经在使用Symfony 3.1,因此使用lazy loading of form choices(Symfony 3.2中的新功能)不会成为问题。不确定这个新功能是否与我的问题有关。
答案 0 :(得分:2)
使用Ajax控制器选项自动完成看起来不错,但是另一个(可能更快?)选项:通过hinclude渲染表单。
Ajax认为,hinclude是一个用于“延迟”加载页面部分的JS库。 Symfony带有集成支持(official documentation)。
你如何使用它:
formAction
使用此代码呈现表单:
{{render_hinclude(controller('... :: form'),{'default':'Loading ...'})}}
您可能希望在原始控制器操作中保留表单处理,因此请修改生成表单的“操作”,如下所示:
$ form = $ this-> createForm(new FormType(),$ obj,array('action'=> $ this-> generateUrl('original_form_action')));
答案 1 :(得分:1)
考虑到您的用例,最好的方法是使用自动填充功能。这是我一直在使用的Symfony bundle,它很棒。我做了一些覆盖它的javascript(自动填充程序),根据我的情况增强了一些功能。
答案 2 :(得分:1)
我写了一个包(Alsatian/FormBundle),它可以在服务器端执行您想要的操作。
How to avoid loading each entities by each form rendering:
abstract class AbstractExtensibleChoicesType extends AbstractRoutableType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('choices',array());
}
}
如何使用缓存内容填充表单字段:
这是你自己的逻辑,我建议:创建一个只返回(作为HTML)的控制器:
<option value="1">Option 1</option>
<option value="2">Option 2</option>
在控制器中设置Maxage:
/*
* @Route(...)
* @Cache(maxage=64000)
*/
public function getOptionsAction(Request $request) // Home
{
$choices = $this->getDoctrine()->getManager()->getRepository //....
return $this->render(/*...*/);
}
使用javascript加载此网址并将html结果放入您的选择字段。
如果你使用像Select2这样的东西: 您的Controller也可以将选项作为JSONReponse()返回,然后您可以直接从select2 ajax选项加载此JSON(请参阅包文档,以及我如何使用它)。
在Form :: PRE_SUBMIT事件中获取总结选项(如果使用表单进行编辑,也可以使用PRE_SET_DATA),并将这些选项重新输入到字段中。