添加JQuery的自动完成在Symfony2的实体领域 [英] Adding JQuery Autocomplete in Symfony2 Entity field

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

问题描述

我有一个一对多relationships.I城市和选民实体要到实体领域(数以千计的记录在下拉)转换为文本输入,这样我可以实现JQuery的自动完成功能,当用户开始输入2个字母。经过近两个星期,我成功地创建了DataTransformer这在一个文本input.Now我的问题是,我仍然在学习的JQuery / Ajax和我感到困惑如何在Symfony2的形式实现它变换实体领域。

  // formtype.php


私人$ EntityManager的;

公共职能__construct(的ObjectManager $ EntityManager的)
{
  $这个 - >的EntityManager = $ EntityManager的;
}
$建设者
         - >添加('地址',空,阵列(
        error_bubbling'=>真正
      ))
         - >添加('市','文字',阵列(
        标签=> 输入您的城市,
        //'error_bubbling'=>真正,
        invalid_message'=> 这城市,你进入未列出,
      ))
 $ builder->获得(城市)
       - > addModelTransformer(新CityAutocompleteTransformer($这个 - >的EntityManager));

//datatransformer.php

类CityAutocompleteTransformer实现DataTransformerInterface
{
私人$ EntityManager的;

公共职能__construct(的ObjectManager $ EntityManager的)
{
    $这个 - >的EntityManager = $ EntityManager的;
}

公共职能变换($市)
{
    如果(空=== $市){
        返回 '​​';
    }

    返回$都市>的getName();
}

公共职能reverseTransform($的cityName)
{
    如果(!$的cityName){
        返回;
    }

    $城市= $这个 - >的EntityManager
         - > getRepository('DuterteBundle:城) - > findOneBy(阵列(名称=> $的cityName));

    如果(空=== $市){
        抛出新TransformationFailedException(sprintf的(有没有%的存在,
            $的cityName
        ));
    }

    返回$城市;
 }
}
 

// Controller.php这样

 公共职能createAction(请求$要求)
{
    $实体=新选民();
    $形式= $这个 - > createCreateForm($实体);
    $形式 - >的handleRequest($请求);

    $验证= $这个 - >获得('验证');
    $错误=用$ validator->验证($实体);
    如果($形式 - >的isValid()){
        $ EM = $这个 - > getDoctrine() - > getManager();
        $的EM>坚持($实体);
        $的EM>的flush();


        $这个 - > addFlash(危险,您已成功加入!欢迎越来越多的支持者,不要忘了分享,并邀请这给你的朋友和亲戚,请单击下面共享按钮,有一个神奇的一天!);

        //返回$这个 - >重定向($这个 - > generateUrl('voters_show',阵列('身份证'=> $实体 - >的getId())));
        返回$这个 - >重定向($这个 - > generateUrl('voters_list'));
    } 其他 {

        $这个 - > addFlash('危险','Oppss出头了问题,检查错误,老兄!);

        返回$这个 - >渲染('DuterteBundle:投票人:neww.html.twig,阵列(
            实体=> $实体,
            '形式'=> $形式 - > CreateView的()
        ));
    }
}

/ **
 *创建一个表单创建一个选民的实体。
 *
 * @参数选民$实体,该实体
 *
 * @返回\ Symfony的\分量\表\本的形式
 * /
私有函数createCreateForm(选民$实体)
{
    $的EntityManager = $这个 - > getDoctrine() - > getManager();
    $形式= $这个 - >的CreateForm(新VotersType($ EntityManager的),$实体,//这里我通过实体管理器,使其工作
阵列(
        '行动'=> $这个 - > generateUrl('voters_create),
        '方法'=> POST,
    ));

    $形式 - >添加(提交,提交,阵列(
        标签=> 我定投市长Duterte
    ));

    返回$形式;
}
 

通过这个code,我可以成功地创建一个新的投票,将抛出验证错误(invalid_message在formtype),当用户输入不符合那些已经保存在我现在缺乏database.What城市名就是我想实现当用户键入至少输入两个字母的JQuery的自动完成

树枝的一部分

  // twig.php

  {{form_start(形式,{ATTR:{NOVALIDATE:NOVALIDATE'}})}}
        {{form_errors(表)}}
        {{form_row(form.comments,{'ATTR:{占位符:你为什么要'}})}}
        {{form_row(form.email,{'ATTR:{占位符:电子邮件是可选的,你可以把它blank.But如果要包括你的电子邮件,确保它是您有效的电子邮件'}})} }
        {{form_end(表)}}
 

输入图像的描述在这里

正如你所看到的,窗体本身是从城市field.Here包含许多领域,抛开,城市字段是一个下拉由来自database.I一千余项可以成功地转化这个下拉到文本框使用DataTransformer.So这里的问题是如何实现JQuery的自动完成这里面的形式与众多领域。

任何帮助是pciated AP $ P $

更新

基于用户Frankbeen的回答

,我添加了一个动作我控制器内

 公共职能autocompleteAction(请求$要求)
{
    $名称=阵列();
    $长期=修剪(用strip_tags($请求 - >获得('术语')));

    $ EM = $这个 - > getDoctrine() - > getManager();

    $实体= $的EM> getRepository('DuterteBundle:城) - > createQueryBuilder('C')
        - 化合物其中('c.name这样的:名称)
        - >的setParameter('名','%'$术语%。)
        - > getQuery()
        - >的getResult();

    的foreach($实体$实体)
    {
        $名称[] = $实体 - >的getName()({$实体 - > getProvince()})。
    }

    $响应=新JsonResponse();
    $响应 - >使用setData($名);

    返回$反应;
}
 

和也的js文件

  {%块的JavaScript%}
{{父()}}
<脚本的src =// code.jquery.com / UI / 1.10.3 / jQuery的-ui.js>< / SCRIPT>
<脚本>
    $(函数(){
        功能的日志(消息){
            $(< D​​IV>中)的.text(消息)prependTo(#log)。
            $(#log).scrollTop(0);
        }

        $(#project_bundle_dutertebundle_voters_city)。自动完成({
            来源:{{路径('city_autocomplete')}},
            的minLength:2,
            选择:功能(事件,UI){
            登录(ui.item?
                选择:+ ui.item.value +又名+ ui.item.id:
                没有什么选择,输入了+ THIS.VALUE);
            }
        });
    });
< / SCRIPT>
{%端嵌段%}
 

在这种情况下,在

  $(#project_bundle_dutertebundle_voters_city)。自动完成({
 

部分实际上由Symfony2的现在呈现form.The JQuery的自动完成时,工作提供城市字段的默认ID,但问题是,我无法保存所选的选项,我的内心FormType.php创建的invalid_message验证被触发以及时提交按钮的jQuery脚本被点击

  

选择:Basista(班诗兰省)又名未定义

它告诉选定值的ID是不确定的。

  $(#project_bundle_dutertebundle_voters_city)。自动完成({
            来源:{{路径('city_autocomplete')}},
            的minLength:2,
            选择:功能(事件,UI){
            登录(ui.item?
                选择:+ ui.item.value +又名+ ui.item.id://这个掷不确定
                没有什么选择,输入了+ THIS.VALUE);
            }
        });
 

解决方案

首先,你要开始创建一个路由和行动,返回JSON数据。 jQuery的自动完成远程为您提供了一个$ _GET variabele与索引并希望得到JSON回来。下面是一个使用实体名称的例子的和属性的 $名称

 命名空间的appbundle \控制器;

使用Sensio公司\包\ FrameworkExtraBundle \配置\路径;
使用Symfony的\包\ FrameworkBundle \控制器\控制器;
使用Symfony的\分量\ HttpFoundation \请求;
使用Symfony的\分量\ HttpFoundation \ JsonResponse;

/ **
 *城市控制器。
 *
 * @Route(/城)
 * /
类CityController扩展控制器
{
    / **
     * @Route(/自动完成,名字=city_autocomplete)
     * /
    公共职能autocompleteAction(请求$要求)
    {
        $名称=阵列();
        $长期=修剪(用strip_tags($请求 - >获得('术语')));

        $ EM = $这个 - > getDoctrine() - > getManager();

        $实体= $的EM> getRepository('的appbundle:城) - > createQueryBuilder('C')
            - 化合物其中('c.name这样的:名称)
            - >的setParameter('名','%'$术语%。)
            - > getQuery()
            - >的getResult();

        的foreach($实体$实体)
        {
            $名称[] = $实体 - >的getName();
        }

        $响应=新JsonResponse();
        $响应 - >使用setData($名);

        返回$反应;
    }
}
 

二级你可以做一个树枝观点,就像从jQuery的自动完成功能的来源。唯一的区别是在来源自动完成()函数变量。在那里,你必须与你的路线键指定TE树枝的路径()的功能,例如 city_autocomplete

(这种观点需要另一条路线,另一个(正常)操作。)

 <!DOCTYPE HTML>
< HTML LANG =EN>
< HEAD>
  <元字符集=utf-8>
  <冠军> jQuery用户界面自动完成 - 远程数据源< /标题>
  <链接相对=样式表的href =// code.jquery.com / UI / 1.11.4 /主题/平滑/ jQuery的-ui.css>
  <脚本的src =// code.jquery.com / jQuery的-1.10.2.js>< / SCRIPT>
  <脚本的src =// code.jquery.com / UI / 1.11.4 / jQuery的-ui.js>< / SCRIPT>
  <链接相对=样式表的href =/资源/演示/ style.css的>
  <风格>
  .UI-自动完成加载{
    背景:白色的URL(图像/ UI-anim_basic_16x16.gif)右心不重复;
  }
  < /风格>
  <脚本>
  $(函数(){
    功能的日志(消息){
      $(< D​​IV>中)的.text(消息)prependTo(#log)。
      $(#log).scrollTop(0);
    }

    $(#birds).autocomplete({
      来源:{{路径('city_autocomplete')}},
      的minLength:2,
      选择:功能(事件,UI){
        登录(ui.item?
          选择:+ ui.item.value +又名+ ui.item.id:
          没有什么选择,输入了+ THIS.VALUE);
      }
    });
  });
  < / SCRIPT>
< /头>
<身体GT;

< D​​IV CLASS =UI小部件>
  <标签=鸟与GT;鸟:LT; /标签>
  <输入ID =鸟>
< / DIV>

< D​​IV CLASS =UI小部件的风格=的margin-top:2em的;字体family:宋体>
  结果:
  < D​​IV ID =登陆的风格=高度:200像素;宽度:300像素;溢出:汽车;类=UI小部件内容>< / DIV>
< / DIV>


< /身体GT;
< / HTML>
 

和finaly可以稍微改变这种观点,并用自己的形式。

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 \Symfony\Component\Form\Form 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 AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;

/**
 * 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.

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

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