创建一个'Ajaxified'表单字段类型

时间:2016-07-25 20:35:43

标签: ajax symfony symfony-forms

在我的应用程序中,我有几个表单字段,有很多选项。我遇到的问题类似于this question:在每个页面加载时获取和解析所有选项都很昂贵(Twig一遍又一遍地渲染所有选项,而没有客户端缓存可能)。这个问题让我创建了一种通过AJAX将选项发送到浏览器的方法。相当简单的方法:

  1. 通过AJAX获取所有选项(键值)(例如通过获取/countries.json)并尽可能缓存。 (在这种情况下,国家名称不太可能经常更改)
  2. 使用selectize,select2或类似的插件将选项插入DOM。
  3. 享受更快的表格: - )
  4. 为防止Symfony查询所有选项(不必要:他们通过AJAX加载)我在加载表单时将setMaxResults(0)添加到QueryBuilder(通过控制器添加选项) )。是的,这就是kludge。提交表单时,它仍会执行查询,因为它必须验证所选选项是否存在(并检查约束)。

    我想创建一个custom Form Field Type,将此功能添加到当前EntityType:在呈现表单时不加载选项,但仍检查所选选项是否存在。我发现many examplesdynamically modifying a form有关,但我找不到与修改一个表单字段相关的示例,而与其父表单无关。

    如何创建这样的表单字段类型?什么是一个很好的起点?扩展EntityTypeChoiceType还是其他方法?

    我已经在使用Symfony 3.1,因此使用lazy loading of form choices(Symfony 3.2中的新功能)不会成为问题。不确定这个新功能是否与我的问题有关。

3 个答案:

答案 0 :(得分:2)

使用Ajax控制器选项自动完成看起来不错,但是另一个(可能更快?)选项:通过hinclude渲染表单。

Ajax认为,

hinclude是一个用于“延迟”加载页面部分的JS库。 Symfony带有集成支持(official documentation)。

你如何使用它:

  • 将表单呈现移动到另一个控制器操作,我们称之为formAction
  • 在您的页面上包含hinclude.js(参见官方Github)
  • 使用此代码呈现表单:

    {{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),并将这些选项重新输入到字段中。