2012-08-15 14 views
9

मैं प्रोपेलबंडल के साथ सिम्फनी 2.1 रूपों का उपयोग कर रहा हूं और मैं एक ऐसे फॉर्म को दोबारा करने की कोशिश कर रहा हूं जिसमें वस्तुओं की एक ड्रॉप-डाउन सूची (से चुनने के लिए) की बजाय एक jquery स्वत: पूर्ण फ़ील्ड (AJAX के साथ काम करना) का उपयोग करें। ड्रॉपडाउन सूची के लिए मैं अपने प्रपत्र प्रकार में निम्न कोड (जो लटकती के लिए पूरी तरह से काम किया है) का उपयोग किया गया था:संग्रह के लिए एक सिम्फनी 2 फॉर्म में एक स्वतः पूर्ण फ़ील्ड कैसे जोड़ें और प्रोपेल का उपयोग कैसे करें?

$builder->add('books', 'collection', array(
    'type'   => 'model', 
    'options'  => array(
     'class'  => 'MyVendor\MyBundle\Model\Book', 
     'property' => 'title', 
    ), 
    'allow_add'  => true, 
    'allow_delete' => true, 
    'by_reference' => false, 
    'required'  => false, 
)); 

एक छोटे संदर्भ देने के लिए, मान लीजिए कि हम एक नया "रीडर पैदा कर रहे जाने "ऑब्जेक्ट और हम उपलब्ध" पुस्तक "ऑब्जेक्ट्स की सूची से रीडर की पसंदीदा पुस्तकें चुनना चाहते हैं। एक संग्रह प्रकार का उपयोग किया जाता है ताकि नए "रीडर" फ़ॉर्म में कई "पसंदीदा पुस्तकें" का चयन किया जा सके। अब, मैं उपरोक्त उपयोग करने के लिए उपरोक्त को बदलना चाहता हूं। ऐसा करने के लिए, मैंने Data Transformer to be able to get a Book object from a simple text field को कार्यान्वित करने का प्रयास किया जिसका उपयोग the answer to this Question में इंगित पुस्तक आईडी को पास करने के लिए स्वत: पूर्ण कार्य के लिए किया जा सकता है। हालांकि, मैं डेटा ट्रांसफार्मर को संग्रह प्रकार और प्रोपेल कक्षाओं के साथ काम करने का तरीका समझने में सक्षम नहीं था। मैं एक BookToIdTransformer वर्ग के रूप में Symfony कुकबुक में संकेत दिया और "ReaderType" फ़ाइल में निम्न की कोशिश की बनाई: अपवाद (जाहिरा तौर पर ट्रांसफार्मर की उम्मीद:

$transformer = new BookToIdTransformer(); 
$builder->add(
     $builder->create('books', 'collection', array(
      'type'   => 'text', 
      'allow_add'  => true, 
      'allow_delete' => true, 
      'by_reference' => false, 
      'required'  => false, 
     ))->addModelTransformer($transformer) 
); 
ऊपर के साथ

, मैं एक "getId अपरिभाषित विधि के लिए कॉल करें" मिलता है किताबों का एक प्रस्ताव चयन, एक पुस्तक वस्तु नहीं ..)। क्या किसी को पता है कि इसके बारे में कैसे जाना है? या मुझे बताएं कि क्या प्रोफेल का उपयोग करते हुए सिम्फनी में स्वत: पूर्ण करने के अन्य तरीके हैं और एकाधिक ऑब्जेक्ट्स (जैसे पुस्तकों का संग्रह) चुनने की अनुमति है?

उत्तर

14

जिस समाधान के लिए मैं अंततः गया था वह मेरे पिछले उत्तर से थोड़ा अलग है। मैं अपने "रीडर टाइप" फॉर्म में "संग्रह" फ़ील्ड प्रकार के बजाय "टेक्स्ट" फ़ील्ड प्रकार का उपयोग कर समाप्त हुआ, क्योंकि मैंने Loopj Tokeninput jQuery plugin का उपयोग करके समाप्त किया जो कई मुख्य वस्तुओं (जैसे "पसंदीदा पुस्तक") को मेरे मुख्य से जोड़ने के लिए अनुमति देता है ऑब्जेक्ट (उदाहरण के लिए "रीडर" ऑब्जेक्ट)। इस बात को ध्यान में रखते हुए, मैंने ऑब्जेक्ट्स 'आईडी को पारित करने के लिए एक "डेटा ट्रांसफार्मर" बनाया (टेक्स्ट फ़ील्ड में अल्पविराम से अलग सूची में) एक प्रोपेल ऑब्जेक्ट संग्रह में। कोड को नमूना AJAX ऑब्जेक्ट नियंत्रक समेत निम्नानुसार साझा किया जाता है।

$transformer = new BooksToIdsTransformer(); 
$builder->add(
    $builder->create('books', 'text', array(
     'required' => false, 
    ))->addModelTransformer($transformer) 
); 

"डेटा ट्रांसफार्मर" फ़ाइल इस तरह दिखता है: इस प्रकार

"ReaderType" का महत्वपूर्ण हिस्सा प्रपत्र लग रहा है

// src/MyVendor/MyBundle/Form/DataTransformer/BooksToIdsTransformer.php 
namespace MyVendor\MyBundle\Form\DataTransformer; 

use \PropelObjectCollection; 
use Symfony\Component\Form\DataTransformerInterface; 
use Symfony\Component\Form\Exception\UnexpectedTypeException; 
use MyVendor\MyBundle\Model\BookQuery; 

class BooksToIdsTransformer implements DataTransformerInterface 
{ 
    public function transform($books) 
    { 
     if (null === $books) { 
      return ""; 
     } 

     if (!$books instanceof PropelObjectCollection) { 
      throw new UnexpectedTypeException($books, '\PropelObjectCollection'); 
     } 
     $idsArray = array(); 
     foreach ($books as $book) { 
      $idsArray[] = $book->getId(); 
     } 
     $ids = implode(",", $idsArray); 
     return $ids; 
    } 

    public function reverseTransform($ids) 
    { 
     $books = new PropelObjectCollection(); 

     if ('' === $ids || null === $ids) { 
      return $books; 
     } 

     if (!is_string($ids)) { 
      throw new UnexpectedTypeException($ids, 'string'); 
     } 
     $idsArray = explode(",", $ids); 
     $idsArray = array_filter ($idsArray, 'is_numeric'); 
     foreach ($idsArray as $id) { 
      $books->append(BookQuery::create()->findOneById($id)); 
     } 
     return $books; 
    } 
} 

ajax नियंत्रक है कि एक json संग्रह रिटर्न टोकनिनपुट स्वत: पूर्ण समारोह में "किताबें" निम्नानुसार है:

namespace MyVendor\MyBundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 
use MyVendor\MyBundle\Model\BookQuery; 


class ClassAjaxController extends Controller 
{ 
    public function bookAction(Request $request) 
    { 
     $value = $request->get('q'); 

     $books = BookQuery::create()->findByName('%'.$value.'%'); 

     $json = array(); 
     foreach ($books as $book) { 
      $json[] = array(
       'id' => $book->getId(), 
       'name' => $book->getName() 
      ); 
     } 

     $response = new Response(); 
     $response->setContent(json_encode($json)); 

     return $response; 
    } 
} 

और अंत में, वें "routing.yml" फ़ाइल में ई राउटर:

ajax_book: 
    pattern: /ajax_book 
    defaults: { _controller: MySiteBundle:ClassAjax:book } 
+0

पूरी तरह से स्पष्टीकरण के लिए धन्यवाद। यदि आपके पास कई नियंत्रक क्रियाएं हैं जो JSON प्रतिक्रियाओं को वापस करनी चाहिए, तो मैं अनुशंसा करता हूं कि FOSRestBundle – Narretz

+0

क्या आप अपने व्यू/फॉर्म का स्निपेट जोड़ सकते हैं? – timaschew

+0

@timaschew अगर मुझे अच्छी तरह से याद है (मुझे इसकी आवश्यकता नहीं है), दृश्य में कोड केवल सिम्फनी रूपों के लिए उपयोग किया जाने वाला मानक है। क्षेत्र एक नियमित पाठ इनपुट है। इनपुट की आईडी का उपयोग कर जावास्क्रिप्ट का उपयोग करके टोकनइनपुट प्लगइन द्वारा उस इनपुट में स्वत: पूर्ण कार्यक्षमता को जोड़ा जाता है: $ ("# my-text-input")। टोकन इनपुट ("/ url/to/your/script /"); – RayOnAir

संबंधित मुद्दे