2013-10-28 11 views
6

Robię stronę dla ogłoszeń. Reklama może być różnego rodzaju i dlatego ma różne dane. Na przykład pojazd będzie miał make i model jako dodatkowe dane.Dynamiczna forma (przełącznik podmiotu) symfony2

W tej chwili mam jedną podstawową jednostkę doktryny Advert, która zawiera dane wymagane przez każde ogłoszenie. Poszczególne reklamy z kolei przekazują te dane (doctrine2 discriminatormap)

Muszę wypełnić formularz dynamicznie (za pomocą formularzy ajax i symfony2), jeśli użytkownik zdecyduje się utworzyć reklamę pojazdu Chcę wyświetlić opcje reklamy pojazdu. Ale muszę również zmienić jednostkę, aby miała postać AdvertVehicle.

Czy to możliwe? Czytałem wpis cookbook na stronie Symfony2

„Jak dynamicznie modyfikować formularze formularz Zdarzenia”: To powinno być obsługiwane poprzez wywołanie AJAX z powrotem do aplikacji. W tym kontrolerze możesz przesłać formularz, ale zamiast go przetwarzać, po prostu użyj przesłanego formularza, aby renderować zaktualizowane pola. Odpowiedzi z połączenia AJAX można następnie użyć do aktualizacji widoku.

Rozumiem, jak wykonać wywołanie ajax z powrotem do mojego kontrolera, i rozumiem, jak używać formularza zdarzeń, ale jak uzyskać odpowiedź zrenderowanego select-box (zawierające modele pojazdów na przykład) ? Z nowym AbstractType? lub formbuilder?

A kiedy użytkownik faktycznie przesyła formularz, muszę użyć podmiotu wybranego typu ogłoszenia. Czy mogę zmienić obiekt zgodnie z wyborem użytkownika w formularzu dynamicznie?

Edytuj Sprawdziłem dziedziczenie formularza, które jest wspaniałe, dziękuję. Rozszerzam AdvertType i zastępuję metodę buildForm() i zanim dodaję elementy potrzebne do AdvertVehicleType, nazywam metodę nadrzędną.

dodatkowych wojsk Wyjaśnienie Każde ogłoszenie jednostka zawiera price, description, title i category. Niektóre reklamy zawierają więcej, na przykład make i model. Są one zróżnicowane przez discriminatormap (doctrine2)

Przykład:

// -- Entity 
class CarAdvert extends Advert { 

    protected $model; 
    protected $make; 

} 

// -- Entity 
// -- This uses discriminator mapping 
class Advert { 
    protected $title; 
    protected $description; 
    protected $price; 
    protected $category; 
} 

jeśli użytkownik wybierze kategorię cars chcę użyć podmiot CarAdvert (dla walidacji i utrzymywanie się), jeśli użytkownik wybierze dom hold itemcategory Po prostu chcę użyć normalnej encji Advert.

Jeden poważny problem jest nadal, że nie mogę dowiedzieć się, jak renderować rozszerzoną formę za pośrednictwem ajax. Wszelkie wskazówki na ten temat? Gdy użytkownik wybierze samochód jako kategorię, chcę, aby formularz został zaktualizowany (przez jQuery/ajax), ale jak utworzyć kontroler, który pobierze tylko rozszerzoną część formularza i odeśle html jako odpowiedź (bez użycia gałązki i renderowanie go w widoku, jest to możliwe?

Rozwiązanie:

Patrz odpowiedź poniżej!

+1

Możesz używać dziedziczenia w swoich typach formularzy, unika się duplikowania kodu dla 2 podobnych formularzy Przykład: 'AdvertType' ma 2 pola. 'AdvertVehicleType' może rozszerzyć' AdvertType' w celu dodania 2 pól. Opowiedz nam więcej o swoich jednostkach, w jaki sposób są one zadeklarowane, jak rozróżniasz dwa typy 'Advert', itp. –

+0

Każda aktualizacja tego pytania @Asbestos? Mam do czynienia z podobnym problemem, więc jestem zainteresowany możliwym rozwiązaniem lub doświadczeniem z tym problemem, itd. Dzięki! – acrobat

+1

Mam nadzieję, że zaktualizowana odpowiedź jest wystarczająco dobra @acrobat nie wahaj się zostawić inny komentarz, jeśli potrzebujesz więcej informacji! – Asbestos

Odpowiedz

2

Rozwiązanie:

Rozwiązanie mojego problemu było stworzenie kilku dodatkowych funkcji w sterowniku, aby rozwiązać problem, gdzie chcę, aby móc zmienić podmiot oraz formularz „w locie” Z wybór przez użytkownika ..

public function indexAction(Request $request) 
{ 
    $form = $this->getForm($request); 
    $form->handleRequest($request); 

    return array(
      'form' => $form->createView(), 
      'request' => $request->request, 
    ); 
} 

Gdzie getForm odzyskuje formę (np AdvertVehicleType dla pojazdów lub AdvertType na reklamie „default”).

Sposób getForm wygląda następująco:

private function getForm(Request $request) 
{ 
    $categoryTitle = 'NONE'; 
    $categoryId = $request->request->get('advert', false)['category']; 

    if ($categoryId) { 
     $categoryTitle = $this->getDoctrine()->getRepository('Bundle:Category')->find($categoryId)->getTitle(); 
    } 

    return $this->createForm($this->getFormType($categoryTitle), $this->getEntity($categoryTitle)); 

}

tu pobrać categoryID (który jest wybrany w postaci we wniosku) i retreives się formType z getFormTypeand jednostkę z getEntity.

private function getEntity($categoryTitle) 
{ 
    $entity = new Advert(); 
    switch ($categoryTitle) { 
     case Category::CARS: 
      $entity = new AdvertCar(); 
    } 

    return $entity; 
} 

private function getFormType($categoryTitle) 
{ 
    switch ($categoryTitle) { 
     case Category::CARS: 
      return new AdvertCarType(); 
     default: 
      return new AdvertType(); 
    } 
} 

Aby móc aktualizować to „w locie” z AJAX (ale działa również wtedy, gdy użytkownik próbuje wysłać formularz) I stworzył kolejną akcję w kontrolerze.

Ta akcja renderuje części formularza, które chcę zaktualizować (w wywołaniu ajaxowym), robię to poprzez wybieranie, czego nie potrzebuję w formularzu z ustawieniem gałązek obiektów formularza na wyrenderowane w ten sposób:

{% do form.title.setRendered %} 

(to tylko przykład I rzeczywiście to zrobić dla wszystkich obiektów formie, że nie chcą, aby uczynić

ja po prostu zadzwoń.

{{ form_rest(form) }} 

który będzie odzyskiwał "resztę" formularza, który jest inny dla różnych kategorii.

Teraz powiedzmy, że masz stan, a nie miasto do wyboru. Najpierw wybierz stan, a następnie wyrenderuj miasta dla tego stanu w gałązce (ale wtedy możesz faktycznie wyrenderować potrzebną część, np. {{ form_row(form.towns) }} i zwrócisz ten renderowany szablon jako odpowiedź json i po prostu umieść go w elemencie, który chcesz z jQuery.

$html = $this->renderView('@Bundle/NewAddPage/filter_area.twig', array('form' => $form->createView())); 

a następnie powrocie zmiennej $ HTML w odpowiedzi.

mam nadzieję, że to pomoże i że wyjaśnienie jest wystarczająco dobre, jeśli nie po prostu zrobić komentarz i będę aktualizować ten z moja odpowiedź!