2016-07-25 42 views
5

W mojej aplikacji mam kilka pól formularza z wieloma opcjami. Problem, którego doświadczyłem, jest podobny do this question: pobieranie i analizowanie wszystkich opcji przy każdym ładowaniu strony jest drogie (Twig renderuje wszystkie opcje w kółko, bez możliwości buforowania po stronie klienta). Ten problem spowodował, że utworzyłem sposób na przesłanie opcji przez AJAX do przeglądarki. Dość proste podejście:Tworzenie "Ajaxified" Typ pola formularza

  1. Uzyskaj wszystkie opcje (klucz-wartość) za pośrednictwem AJAX (na przykład pobierając /countries.json) i pamięć podręczną, jeśli to możliwe. (w tym przypadku nie jest bardzo prawdopodobne, że nazwy krajów zmieniają się bardzo często).
  2. Użyj selectize, select2 lub podobnej wtyczki do wstawienia opcji do DOM.
  3. Zapraszamy na szybszą Formularza :-)

Aby zapobiec Symfony z kwerend wszystkie opcje (nie jest to konieczne: oni ładowanie za pośrednictwem AJAX) Dodałem setMaxResults(0) do QueryBuilder gdy formularz jest ładowany (dodając opcję przez kontroler). Tak, to kludge. Wysyłając formularz, nadal będzie wykonywał zapytanie, ponieważ musi sprawdzić, czy wybrana opcja istnieje (i sprawdzić ograniczenia).

Chciałbym utworzyć custom Form Field Type, który dodaje tę funkcję do bieżącego EntityType: nie ładuj opcji podczas renderowania formularza, ale wciąż sprawdź, czy wybrana opcja istnieje. Znalazłem manyexamples powiązane z dynamically modifying a form, ale nie znalazłem przykłady związane z modyfikowaniem tylko jednego pola formularza, niezależnie od jego rodzica formularza.

Jak utworzyć typ pola formularza? Jaki jest dobry punkt wyjścia? Przedłużyć EntityType, ChoiceType lub inne podejście?

Używam już Symfony 3.1, więc używanie lazy loading of form choices (Nowości w Symfony 3.2) nie będzie problemem. Nie jestem pewien, czy ta nowa funkcja jest powiązana z moim problemem.

+0

Prawdopodobny duplikat [Przedłużanie EntityType, aby umożliwić dodatkowe wybory zestaw z połączeń AJAX] (http://stackoverflow.com/questions/30178424/extending-entitytype-to-allow-extra-choices-set-with-ajax-calls) – Alsatian

Odpowiedz

1

Napisałem pakiet (Alsatian/FormBundle), który robi to, co chcesz po stronie serwera.

  • How to avoid loading each entities by each form rendering:

    abstract class AbstractExtensibleChoicesType extends AbstractRoutableType 
    { 
        public function configureOptions(OptionsResolver $resolver) 
        { 
         $resolver->setDefault('choices',array()); 
        } 
    } 
    
  • Jak wypełnić pole formularza z pamięci podręcznej:

To twoja własna logika, chciałbym zaproponować: utworzyć sterownik, który zwraca tylko (jako HTML):

<option value="1">Option 1</option> 
<option value="2">Option 2</option> 

W regulatorze ustawionym Maxage:

/* 
* @Route(...) 
* @Cache(maxage=64000) 
*/ 
public function getOptionsAction(Request $request) // Home 
{ 
    $choices = $this->getDoctrine()->getManager()->getRepository //.... 

    return $this->render(/*...*/); 
} 

użyć JavaScript, aby załadować ten link i umieścić wynik HTML w wybranej dziedzinie.

Jeśli używasz czegoś takiego jak Select2: Twój kontroler może również zwrócić opcje jako JSONReponse(), następnie możesz załadować ten JSON bezpośrednio z opcji select2 ajax (zobacz dokumentację pakietu, w ten sposób go używam).

Get sumitted wyborów w postaci :: zdarzenie PRE_SUBMIT (także PRE_SET_DATA jeśli używasz formularz do edycji), a zaszczepić te wybory do pola.

1

Biorąc pod uwagę twój przypadek, Najlepszym sposobem byłoby użycie autouzupełniania. Oto Symfony bundle, z których korzystałem i jest to niesamowite. Zrobiłem trochę nadpisać jego javascript (autocompleter), aby poprawić kilka funkcji, jak na moim przypadku.

+0

Dzięki za sugestię, mogę użyć tego pakietu jako inspiracji. Nie chcę obsługiwać po stronie serwera, ponieważ wyszukiwanie po stronie klienta jest znacznie szybsze. Nie podoba mi się też ich implementacja kontrolera, ponieważ używa ona Twig do renderowania wyjścia JSON. Czemu?! –

+0

Tak, zamiast używać gałązki do renderowania jsona, napisałem w kontrolerze, aby zwróciło 'JsonResponse' wyniku. Nie trzeba renderować gałązki dla wyjścia json. – Jeet

+0

Nie jestem pewien, czy taki pakiet jest użyteczny - po prostu dodaj bibliotekę Wybranych do swojej strony + kod init, a tutaj robisz z "normalnym" typem jednostki. Następnie, aby uzyskać wzrost wydajności, musisz przejść do opcji "Ajax", aby załadować swoje wpisy. – romaricdrigon

2

Autouzupełnianie z opcją kontrolera Ajax wygląda mi ładnie, ale jest "inna (może szybciej?) Opcja: wyślij formularz przez hinclude.

hinclude to biblioteka JS używana do "odroczenia" obciążenia części strony, pomyślał Ajax. Symfony ma zintegrowaną obsługę (official documentation).

Jak yo używać go:

  • przenieść swoją postać renderowanie do innego działania kontrolera, nazwijmy to formAction
  • obejmują hinclude.js na swojej stronie (por oficjalnej Github)
  • użyć tego kodu do renderowania formularza:

    {{render_hinclude (kontroler ("... :: formularz"), {'default': 'Ładowanie ...„})}}

  • będzie prawdopodobnie chcesz, aby utrzymać formę postępowania w oryginalnej akcji kontrolera, tak zmodyfikować "działanie" formularza wygenerowanego takiego:

    $ form = $ this-> CreateForm (nowy FormType(), $ obj, array ('action' => $ this-> generateUrl ('original_form_action')));