Ajout de la saisie semi-automatique JQuery dans le champ Entité Symfony2

Je souhaite convertir le champ entité (des milliers d’enregistrements dans une liste déroulante) en une entrée de texte afin que je puisse mettre en œuvre l’auto-complétion JQuery lorsque les utilisateurs commencent à taper 2 lettres.Après presque Deux semaines plus tard, j’ai créé avec succès DataTransformer, qui transforme le champ d’entité en une entrée de texte. Maintenant, le problème est que j’apprends toujours le JQuery / Ajax et je ne sais pas comment le mettre en œuvre dans les formulaires Symfony2.

//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->getDocsortingne()->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->getDocsortingne()->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; } 

Avec ce code, je peux créer avec succès un nouveau votant et jetterai des erreurs de validation (invalid_message dans le type de formulaire) lorsqu’un utilisateur a entré un nom de ville qui ne correspond pas à ceux déjà enregistrés dans la firebase database. Ce qui me manque maintenant, c’est que je souhaite implémenter le JQuery autocomplete lorsque le type d’utilisateur saisit au moins deux lettres

La partie brindille

 //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) }} 

entrez la description de l'image ici

Comme vous pouvez le constater, le formulaire lui-même est composé de nombreux champs, à part le champ ville. Ici, le champ ville est une liste déroulante composée de plus de mille entrées de la firebase database. Je peux convertir avec succès ce menu déroulant en champ de texte à l’aide de DataTransformer. Le problème est donc de savoir comment implémenter JQuery Autocomplete dans ce formulaire avec de nombreux champs.

Toute aide est appréciée

Mettre à jour

Basé sur la réponse de l’utilisateur Frankbeen, j’ai ajouté une action dans ma manette

 public function autocompleteAction(Request $request) { $names = array(); $term = sortingm(ssortingp_tags($request->get('term'))); $em = $this->getDocsortingne()->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; } 

Et aussi le fichier js

 {% block javascripts %} {{ parent() }}   $(function() { function log( message ) { $( "
" ).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 ); } }); }); {% endblock %}

Dans ce cas, le

  $( "#project_bundle_dutertebundle_voters_city").autocomplete({ 

partie est en réalité l’identifiant par défaut du champ ville fourni par Symfony2 lors du rendu du formulaire. La saisie semi-automatique JQuery fonctionne à présent, mais le problème est que je ne peux pas enregistrer l’option sélectionnée, la validation invalid_message que j’ai créée dans FormType.php est également déclenchée. le script JQuery lorsque vous cliquez sur le bouton d’envoi

Sélectionné: Basista (Province du Pangasinan) dit non défini

qui indique que l’identifiant de la valeur sélectionnée est indéfini

 $( "#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 ); } }); 

Tout d’abord, vous devez commencer à créer une route et une action qui renvoie les données JSON. La télécommande à complétion automatique de JQuery vous donne une variabele $ _GET avec le terme ‘index’ et veut recevoir le JSON. Voici un exemple qui utilise une entité avec le nom City et une propriété $ 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 = sortingm(ssortingp_tags($request->get('term'))); $em = $this->getDocsortingne()->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; } } 

Secondaire, vous pouvez créer une vue de brindille tout comme la source de la saisie semi-automatique de jQuery. La seule différence est la variable source dans la fonction autocomplete () . Là, vous devez spécifier la fonction path () de twig avec votre clé de route, par exemple city_autocomplete .

(Cette vue nécessite une autre route et une autre action (normale).)

     jQuery UI Autocomplete - Remote datasource         
Result:

Enfin, vous pouvez légèrement modifier cette vue et utiliser votre propre formulaire.

Enfin, après avoir approfondi mon code Symfony, j’ai finalement trouvé la solution. À l’aide du code fourni par l’utilisateur Frankbeen, j’ai ajouté quelques “ajustements” pour que JQuery fonctionne enfin. Le coupable se trouve dans le contrôleur.

 $names[] = $entity->getName()."({$entity->getProvince()})"; 

L’entité de ville est liée à l’entité de province dans une relation un à plusieurs.Etant donné que l’entité de ville a des milliers de noms (enregistrements), il est probable que certaines valeurs auront le même nom. Il est donc utile d’append une province associée pour éviter les confusions chez les utilisateurs.

San Francisco (Province de Russie), San Francisco (Province de Chine), San Francisco (Province du Portugal)

entrez la description de l'image ici

Maintenant, puisque les noms sont maintenant “différents” dans les noms déjà enregistrés dans la firebase database, la validation invalid_message déclenchera les erreurs. Ma solution consiste à “nettoyer” les données soumises en supprimant les provinces ajoutées avant de comparer les valeurs soumises par l’utilisateur aux valeurs du firebase database. À l’intérieur du DataTransformer, j’ai ajouté du code

 public function reverseTransform($cityNameConcat) { $cityName = preg_replace("/\([^)]+\)/", "", $cityNameConcat); 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; } 

Maintenant, JQuery fonctionne enfin et la sauvegarde dans la firebase database est également une réussite. Enfin,

 $( "#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 ); } }); 

Est changé en

  

Maintenant, l’erreur ‘Undefined’ est partie.

Voici une solution pour append un champ concernant la réponse donnée par le contrôleur Symfony. En cas de succès, ajoutez les champs souhaités en renvoyant un object. Ensuite, dans la sélection, vous pouvez y accéder par ui.item.fields

 $('#mySelector').autocomplete({ source : function(requete, reponse) { lettre = { lettre: $('#lettre').val() }; $.ajax({ url: Routing.generate('chargementSource'), dataType: 'json', data : lettre, success: function (donnee) { reponse( $.map(donnee, function (object) { return { value: '' + object.nom + ' ' + object.prenom +', '+ object.adresse +' '+ object.codepostal +', '+ object.ville + '', id: object.id } }) ); } }); }, select: function (event, ui) { $('#myId').val(ui.item.id); //alert(ui.item.id); //$('#myId').val(ui.elem.value); return false; } });