在 Symfony2 实体字段中添加 JQuery 自动完成功能 [英] Adding JQuery Autocomplete in Symfony2 Entity field

查看:22
本文介绍了在 Symfony2 实体字段中添加 JQuery 自动完成功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一对多关系中有一个城市和选民实体.我想将实体字段(下拉列表中的数千条记录)转换为文本输入,以便在用户开始输入 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>

最后,您可以稍微更改此视图并使用您自己的表单.

I have a city and voters entity in a one to many relationships.I want to convert the entity field(thousands of records in a dropdown) to a text input so that I can implement the JQuery autocomplete when users start typing 2 letters.After almost two weeks,I successfully created the DataTransformer which transform entity field in to a text input.Now my problem is I am still learning the JQuery/Ajax and I am confused how to implement it in Symfony2 forms.

//formtype.php


private $entityManager;

public function __construct(ObjectManager $entityManager)
{
  $this->entityManager = $entityManager;
}
$builder
        ->add('address', null, array(
        'error_bubbling' => true
      ))
        ->add('city', 'text', array(
        'label' => 'Type your city',
        //'error_bubbling' => true,
        'invalid_message' => 'That city you entered is not listed',
      ))
 $builder->get('city')
      ->addModelTransformer(new CityAutocompleteTransformer($this->entityManager));

//datatransformer.php

class CityAutocompleteTransformer implements DataTransformerInterface
{
private $entityManager;

public function __construct(ObjectManager $entityManager)
{
    $this->entityManager = $entityManager;
}

public function transform($city)
{
    if (null === $city) {
        return '';
    }

    return $city->getName();
}

public function reverseTransform($cityName)
{
    if (!$cityName) {
        return;
    }

    $city = $this->entityManager
        ->getRepository('DuterteBundle:City')->findOneBy(array('name' => $cityName));

    if (null === $city) {
        throw new TransformationFailedException(sprintf('There is no "%s" exists',
            $cityName
        ));
    }

    return $city;
 }
}

//controller.php

public function createAction(Request $request)
{
    $entity = new Voters();
    $form = $this->createCreateForm($entity);
    $form->handleRequest($request);

    $validator = $this->get('validator');
    $errors = $validator->validate($entity);
    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($entity);
        $em->flush();


        $this->addFlash('danger', 'You are successfully added!, Welcome to the growing Supporters, dont forget to share and invite this to your friends and relatives, click share buttons below, have a magical day!');

        //return $this->redirect($this->generateUrl('voters_show', array('id' => $entity->getId())));
        return $this->redirect($this->generateUrl('voters_list'));
    } else {

        $this->addFlash('danger', 'Oppss somethings went wrong, check errors buddy!');

        return $this->render('DuterteBundle:Voters:neww.html.twig', array(
            'entity' => $entity,
            'form'   => $form->createView(),
        ));
    }
}

/**
 * Creates a form to create a Voters entity.
 *
 * @param Voters $entity The entity
 *
 * @return SymfonyComponentFormForm The form
 */
private function createCreateForm(Voters $entity)
{   
    $entityManager = $this->getDoctrine()->getManager();
    $form = $this->createForm(new VotersType($entityManager), $entity, //here i passed the entity manager to make it work
array(
        'action' => $this->generateUrl('voters_create'),
        'method' => 'POST',
    ));

    $form->add('submit', 'submit', array(
        'label' => 'I Will Vote Mayor Duterte'
    ));

    return $form;
}

With this code, I can successfully create a new voter and will throw validation errors(invalid_message in formtype) when a user entered a city name that does not match those already saved in the database.What I am lacking now is I want to implement the JQuery autocomplete when the user type enter at least two letters

The Twig part

//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 is optional, you may leave it blank.But if you want to include your email, make sure it is your valid email '}}) }}
        {{ form_end(form) }}    

As you can see, the form itself is consist of many fields, aside from the city field.Here, the city field is a dropdown consists of more than one thousand entries from database.I can successfully convert this dropdown into textfield by using DataTransformer.So the problem here is how to implement JQuery Autocomplete inside this form with many fields.

Any help is appreciated

Update

Based on user Frankbeen's answer, I Added an action inside my controller

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 as $entity)
    {
        $names[] = $entity->getName()."({$entity->getProvince()})";
    }

    $response = new JsonResponse();
    $response->setData($names);

    return $response;
}

And also the js file

{% block javascripts %}
{{ parent() }}
<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
    $(function() {
        function log( message ) {
            $( "<div>" ).text( message ).prependTo( "#log" );
            $( "#log" ).scrollTop( 0 );
        }

        $( "#project_bundle_dutertebundle_voters_city").autocomplete({
            source: "{{ path('city_autocomplete') }}",
            minLength: 2,
            select: function( event, ui ) {
            log( ui.item ?
                "Selected: " + ui.item.value + " aka " + ui.item.id :
                "Nothing selected, input was " + this.value );
            }
        });
    });
</script>
{% endblock %}

In this case, the

  $( "#project_bundle_dutertebundle_voters_city").autocomplete({

part is actually the default id of city field provided by Symfony2 when rendering the form.The JQuery autocomplete now is working , but the problem is , I cannot save the selected option, the invalid_message validation I created inside FormType.php is triggered as well as the JQuery script when submit button is clicked

Selected: Basista (Pangasinan Province) aka undefined

which tells that the Id of the selected value is undefined

$( "#project_bundle_dutertebundle_voters_city").autocomplete({
            source: "{{ path('city_autocomplete') }}",
            minLength: 2,
            select: function( event, ui ) {
            log( ui.item ?
                "Selected: " + ui.item.value + " aka " + ui.item.id ://this throw undefined
                "Nothing selected, input was " + this.value );
            }
        });

解决方案

First you have to start creating a route and action that returns json data. JQuery's autocomplete remote gives you a $_GET variabele with the index 'term' and wants to receive JSON back. Here is an example that uses an Entity with the name City and a property $name

namespace AppBundleController;

use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationJsonResponse;

/**
 * City controller.
 *
 * @Route("/city")
 */
class CityController extends Controller
{
    /**
     * @Route("/autocomplete", name="city_autocomplete")
     */
    public function 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 as $entity)
        {
            $names[] = $entity->getName();
        }

        $response = new JsonResponse();
        $response->setData($names);

        return $response;
    }
}

Secondary you can make a twig view just like the source from jQuery's autocomplete. The only difference is the source variable in the autocomplete() function . There you have to specify te twig's path() function with your route key eg city_autocomplete.

(This view needs another route and another (normal) action.)

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>jQuery UI Autocomplete - Remote datasource</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">
  <style>
  .ui-autocomplete-loading {
    background: white url("images/ui-anim_basic_16x16.gif") right center no-repeat;
  }
  </style>
  <script>
  $(function() {
    function log( message ) {
      $( "<div>" ).text( message ).prependTo( "#log" );
      $( "#log" ).scrollTop( 0 );
    }

    $( "#birds" ).autocomplete({
      source: "{{ path('city_autocomplete') }}",
      minLength: 2,
      select: function( event, ui ) {
        log( ui.item ?
          "Selected: " + ui.item.value + " aka " + ui.item.id :
          "Nothing selected, input was " + this.value );
      }
    });
  });
  </script>
</head>
<body>

<div class="ui-widget">
  <label for="birds">Birds: </label>
  <input id="birds">
</div>

<div class="ui-widget" style="margin-top:2em; font-family:Arial">
  Result:
  <div id="log" style="height: 200px; width: 300px; overflow: auto;" class="ui-widget-content"></div>
</div>


</body>
</html>

And finaly you can slightly change this view and use your own form.

这篇关于在 Symfony2 实体字段中添加 JQuery 自动完成功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆