在 Symfony2 实体字段中添加 JQuery 自动完成功能 [英] Adding JQuery Autocomplete in Symfony2 Entity field
问题描述
我在一对多关系中有一个城市和选民实体.我想将实体字段(下拉列表中的数千条记录)转换为文本输入,以便在用户开始输入 2 个字母时实现 JQuery 自动完成.差不多两周后,我成功创建了将实体字段转换为文本输入的 DataTransformer.现在我的问题是我仍在学习 JQuery/Ajax,我很困惑如何在 Symfony2 表单中实现它.
//formtype.php私人 $entityManager;公共函数 __construct(ObjectManager $entityManager){$this->entityManager = $entityManager;}$builder->add('地址', null, 数组('error_bubbling' =>真的))->add('城市', '文本', 数组('标签' =>'输入你的城市',//'error_bubbling' =>真的,'invalid_message' =>'您输入的城市未列出',))$builder->get('city')->addModelTransformer(new CityAutocompleteTransformer($this->entityManager));//数据转换器.php类 CityAutocompleteTransformer 实现 DataTransformerInterface{私人 $entityManager;公共函数 __construct(ObjectManager $entityManager){$this->entityManager = $entityManager;}公共功能转换($city){if (null === $city) {返回 '';}返回 $city->getName();}公共函数 reverseTransform($cityName){如果 (!$cityName) {返回;}$city = $this->entityManager->getRepository('DuterteBundle:City')->findOneBy(array('name' => $cityName));if (null === $city) {throw new TransformationFailedException(sprintf('没有%s"存在',$城市名称));}返回 $city;}}
//controller.php
public function createAction(Request $request){$entity = 新选民();$form = $this->createCreateForm($entity);$form->handleRequest($request);$validator = $this->get('validator');$errors = $validator->validate($entity);如果 ($form->isValid()) {$em = $this->getDoctrine()->getManager();$em->persist($entity);$em->flush();$this->addFlash('danger', '您已成功添加!,欢迎成长中的支持者,别忘了分享并邀请您的亲朋好友,点击下方的分享按钮,有一个神奇的一天!');//return $this->redirect($this->generateUrl('voters_show', array('id' => $entity->getId())));返回 $this->redirect($this->generateUrl('voters_list'));} 别的 {$this->addFlash('danger', 'Oppss 出问题了,检查错误,伙计!');return $this->render('DuterteBundle:Voters:neww.html.twig', array('实体' =>$实体,'形式' =>$form->createView(),));}}/*** 创建一个表单来创建一个 Voters 实体.** @param Voters $entity 实体** @return SymfonyComponentFormForm 表单*/私有函数 createCreateForm(Voters $entity){$entityManager = $this->getDoctrine()->getManager();$form = $this->createForm(new VotersType($entityManager), $entity,//这里我通过了实体管理器使其工作大批('动作' =>$this->generateUrl('voters_create'),'方法' =>'邮政',));$form->add('提交', '提交', 数组('标签' =>我将投票给杜特尔特市长"));返回 $form;}
使用此代码,我可以成功创建一个新的投票者,并在用户输入的城市名称与数据库中已保存的城市名称不匹配时抛出验证错误(formtype 中的 invalid_message).我现在缺少的是我想要的当用户输入至少两个字母时实现 JQuery 自动完成
树枝部分
//twig.php{{ form_start(form, {attr: {novalidate: 'novalidate'}} ) }}{{ form_errors(form) }}{{ form_row(form.comments,{'attr': {'placeholder': 'Why You Want '}}) }}{{ form_row(form.email,{'attr': {'placeholder': 'Email 是可选的,您可以将其留空.但如果您想包含您的电子邮件,请确保它是您的有效电子邮件 '}}) }}{{ form_end(form) }}
如您所见,表单本身由许多字段组成,除了城市字段.这里,城市字段是一个下拉列表,由数据库中的一千多个条目组成.我可以成功地将此下拉列表转换为文本字段使用DataTransformer.所以这里的问题是如何在这个有很多字段的表单中实现JQuery Autocomplete.
感谢任何帮助
更新
根据用户 Frankbeen 的回答,我在控制器中添加了一个操作
public function autocompleteAction(Request $request){$names = array();$term = trim(strip_tags($request->get('term')));$em = $this->getDoctrine()->getManager();$entities = $em->getRepository('DuterteBundle:City')->createQueryBuilder('c')->where('c.name LIKE :name')->setParameter('name', '%'.$term.'%')->getQuery()->getResult();foreach ($entities 作为 $entity){$names[] = $entity->getName()."({$entity->getProvince()})";}$response = new JsonResponse();$response->setData($names);返回 $response;}
还有js文件
{% 阻止 javascripts %}{{ 父母()}}<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script><脚本>$(函数(){功能日志(消息){$( "" ).text( message ).prependTo( "#log" );$( "#log" ).scrollTop( 0 );}$(#project_bundle_dutertebundle_voters_city").自动完成({来源:{{ path('city_autocomplete')}}",最小长度:2,选择:函数(事件,用户界面){日志( ui.item ?已选择:" + ui.item.value + 又名" + ui.item.id :"没有选择,输入是" + this.value );}});});{% 结束块 %}在这种情况下,
$( "#project_bundle_dutertebundle_voters_city").autocomplete({
part 实际上是 Symfony2 在渲染表单时提供的城市字段的默认 id.JQuery 自动完成现在正在工作,但问题是,我无法保存选择的选项,我在 FormType.php 中创建的 invalid_message 验证被触发以及点击提交按钮时的 JQuery 脚本
<块引用>已选择:Basista (Pangasinan Province) aka undefined
表示所选值的Id未定义
$( "#project_bundle_dutertebundle_voters_city").autocomplete({来源:{{ path('city_autocomplete')}}",最小长度:2,选择:函数(事件,用户界面){日志( ui.item ?"已选择:" + ui.item.value + " aka " + ui.item.id ://this throw undefined"没有选择,输入是" + this.value );}});
解决方案 首先,您必须开始创建返回 json 数据的路由和操作.JQuery 的自动完成远程 为您提供带有索引term"的 $_GET 变量并希望收到 JSON.这是一个使用名称为 City 和属性 $name
的实体的示例命名空间 AppBundleController;使用 SensioBundleFrameworkExtraBundleConfigurationRoute;使用 SymfonyBundleFrameworkBundleControllerController;使用 SymfonyComponentHttpFoundationRequest;使用 SymfonyComponentHttpFoundationJsonResponse;/***城市控制器.** @Route("/城市")*/类 CityController 扩展控制器{/*** @Route("/autocomplete", name="city_autocomplete")*/公共功能 autocompleteAction(Request $request){$names = array();$term = trim(strip_tags($request->get('term')));$em = $this->getDoctrine()->getManager();$entities = $em->getRepository('AppBundle:City')->createQueryBuilder('c')->where('c.name LIKE :name')->setParameter('name', '%'.$term.'%')->getQuery()->getResult();foreach ($entities 作为 $entity){$names[] = $entity->getName();}$response = new JsonResponse();$response->setData($names);返回 $response;}}
第二,你可以制作一个树枝视图,就像来自 jQuery 的自动完成的源一样.唯一的区别是 autocomplete() 函数中的 source 变量.在那里你必须用你的路由键指定 te twig 的 path() 函数,例如 city_autocomplete.
(这个视图需要另一个路由和另一个(正常)动作.)
<html lang="zh-cn"><头><meta charset="utf-8"><title>jQuery UI 自动完成 - 远程数据源</title><link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"><script src="//code.jquery.com/jquery-1.10.2.js"></script><script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script><link rel="stylesheet" href="/resources/demos/style.css"><风格>.ui-自动完成加载{背景:白色 url("images/ui-anim_basic_16x16.gif") 右中心不重复;}</风格><脚本>$(函数(){功能日志(消息){$( "" ).text( message ).prependTo( "#log" );$( "#log" ).scrollTop( 0 );}$( "#birds" ).autocomplete({来源:{{ path('city_autocomplete')}}",最小长度:2,选择:函数(事件,用户界面){日志( ui.item ?已选择:" + ui.item.value + 又名" + ui.item.id :"没有选择,输入是" + this.value );}});});头部><身体><div class="ui-widget"><label for="birds">鸟类:</label><输入id=鸟"><div class="ui-widget" style="margin-top:2em; font-family:Arial">结果:<div id="log" style="height: 200px; width: 300px; overflow: auto;"class="ui-widget-content"></div>