Czy istnieje łatwy sposób ustawienia wartości domyślnej dla pola formularza tekstowego?
Czy istnieje łatwy sposób ustawienia wartości domyślnej dla pola formularza tekstowego?
Odpowiedzi:
Można go łatwo używać podczas tworzenia z:
->add('myfield', 'text', array(
'label' => 'Field',
'empty_data' => 'Default value'
))
'data'
klucz na'value'
empty_data
data
jest bezużyteczna - nadpisuje zapisaną wartość. empty_data
nie pokazuje wartości, używa jej przy przesłaniu pustej wartości i uniemożliwia zapisanie niezaznaczonych wyborów.
możesz ustawić wartość domyślną za pomocą empty_data
$builder->add('myField', 'number', ['empty_data' => 'Default value'])
Rozważałem to kilka razy w przeszłości, więc pomyślałem, że zanotuję różne pomysły, które miałem / wykorzystałem. Coś może się przydać, ale żadne z nich nie jest "idealnym" rozwiązaniem Symfony2.
Konstruktor W Entity możesz zrobić $ this-> setBar ('wartość domyślna'); ale jest to wywoływane za każdym razem, gdy ładujesz jednostkę (db lub nie) i jest trochę niechlujne. Działa jednak dla każdego typu pola, ponieważ możesz tworzyć daty lub cokolwiek innego, czego potrzebujesz.
Jeśli oświadczenia w ramach get to nie, nie zrobiłbym tego, ale możesz.
return ( ! $this->hasFoo() ) ? 'default' : $this->foo;
Fabryka / instancja . Wywołaj funkcję statyczną / klasę pomocniczą, która zapewnia domyślną jednostkę wstępnie wypełnioną danymi. Na przykład
function getFactory() {
$obj = new static();
$obj->setBar('foo');
$obj->setFoo('bar');
return $obj;
}
Niezbyt idealne, biorąc pod uwagę, że będziesz musiał zachować tę funkcję, jeśli dodasz dodatkowe pola, ale oznacza to, że oddzielasz ustawienia / domyślne ustawienia danych od tych, które są generowane z bazy danych. Podobnie możesz mieć wiele getFactories, jeśli potrzebujesz różnych domyślnych danych.
Encje Rozszerzone / Refleksyjne Utwórz Encję rozszerzającą (np. FooCreate rozszerza Foo), która dostarcza domyślne dane w czasie tworzenia (poprzez konstruktor). Podobnie jak w przypadku fabryki / instancji, tylko inne podejście - osobiście preferuję metody statyczne.
Ustaw dane przed formularzem kompilacji W konstruktorach / usłudze wiesz, czy masz nową jednostkę lub czy została ona wypełniona z bazy danych. Dlatego możliwe jest wywołanie zestawu danych z różnych pól, gdy przechwytujesz nową jednostkę. Na przykład
if( ! $entity->isFromDB() ) {
$entity->setBar('default');
$entity->setDate( date('Y-m-d');
...
}
$form = $this->createForm(...)
Zdarzenia formularza Podczas tworzenia formularza ustawiasz domyślne dane podczas tworzenia pól. Możesz zastąpić to nasłuchiwanie zdarzeń Use PreSetData. Problem z tym polega na tym, że powielasz obciążenie formularza / powielasz kod i utrudniasz utrzymanie / zrozumienie.
Rozszerzone formularze Podobne do zdarzeń Form, ale wywołujesz inny typ w zależności od tego, czy jest to jednostka db / new. Rozumiem przez to, że masz FooType, który definiuje twój formularz edycji, BarType rozszerza FooType to i ustawia wszystkie dane w polach. Następnie w kontrolerze możesz po prostu wybrać, który typ formularza ma być wywołany. To jest do bani, jeśli masz niestandardowy motyw i lubisz wydarzenia, powoduje to zbyt wiele konserwacji, jak na mój gust.
Twig Możesz stworzyć swój własny motyw i ustawić domyślne dane używając opcji wartości, gdy robisz to dla każdego pola. Nic nie stoi na przeszkodzie, aby zawinąć to w motyw formularza, jeśli chcesz, aby szablony były czyste, a formularz wielokrotnego użytku. na przykład
form_widget(form.foo, {attr: { value : default } });
JS Wypełnienie formularza funkcją JS byłoby trywialne, gdyby pola były puste. Możesz na przykład zrobić coś z symbolami zastępczymi. To jednak zły, zły pomysł.
Formularze jako usługa Dla jednego z dużych projektów opartych na formularzach, które zrobiłem, stworzyłem usługę, która generowała wszystkie formularze, wykonywała całe przetwarzanie itp. Było tak, ponieważ formularze miały być używane przez wielu kontrolerów w wielu środowiskach i podczas gdy formularze były generowane / obsługiwane w ten sam sposób, inaczej były wyświetlane / interakcje (np. obsługa błędów, przekierowania itp.). Piękno tego podejścia polegało na tym, że możesz ustawić domyślne dane, robić wszystko, czego potrzebujesz, generalnie obsługiwać błędy itp., A wszystko to jest zawarte w jednym miejscu.
Wniosek Jak widzę, napotkasz ten sam problem za każdym razem - gdzie znajdują się domyślne dane?
W tym celu za każdym razem podchodziłem do problemu inaczej. Na przykład opcję „biuletyn” formularza rejestracji można łatwo (i logicznie) ustawić w konstruktorze tuż przed utworzeniem formularza. Kiedy tworzyłem kolekcje formularzy, które były ze sobą połączone (np. Które przyciski radiowe w różnych typach formularzy były ze sobą połączone), użyłem Event Listeners. Kiedy budowałem bardziej skomplikowaną jednostkę (np. Taką, która wymagała dzieci lub wielu domyślnych danych), użyłem funkcji (np. „GetFactory”), aby utworzyć element, którego potrzebuję.
Nie wydaje mi się, aby było jedno „właściwe” podejście, ponieważ za każdym razem, gdy miałem ten wymóg, było ono nieco inne.
Powodzenia! Mam nadzieję, że w każdym razie dałem Ci trochę do myślenia i nie włóczyłem się zbytnio;)
Jeśli potrzebujesz ustawić wartość domyślną, a Twój formularz odnosi się do encji, powinieneś zastosować następujące podejście:
// buildForm() method
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
...
->add(
'myField',
'text',
array(
'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
)
);
}
W przeciwnym razie myField
zawsze zostanie ustawiona wartość domyślna, zamiast pobierać wartość z jednostki.
$options['data']->getMyField()
z$option['data']['myField']
empty_data
: Ta opcja określa, jaką wartość pole zwróci, gdy przesłana wartość jest pusta. Nie ustawia wartości początkowej
Możesz ustawić wartość domyślną dla pokrewnego pola w swojej klasie modelu (w definicji mapowania lub samodzielnie ustaw wartość).
Ponadto FormBuilder daje możliwość ustawienia wartości początkowych za pomocą metody setData () . Konstruktor formularzy jest przekazywany do metody createForm () klasy formularza.
Sprawdź również ten link: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class
Jeśli twój formularz jest powiązany z jednostką, po prostu ustaw domyślną wartość na samej encji za pomocą metody konstruowania:
public function __construct()
{
$this->field = 'default value';
}
'mapped' => false
). Użyj setData(...)
do tych.
Podejście 1 (z http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/ )
Po prostu ustaw wartość domyślną w swojej encji, w deklaracji zmiennej lub w konstruktorze:
class Entity {
private $color = '#0000FF';
...
}
lub
class Entity {
private $color;
public function __construct(){
$this->color = '#0000FF';
...
}
...
}
Podejście 2 z komentarza w powyższym linku, a także odpowiedź Dmitriya (nie zaakceptowana) z Jak ustawić wartość domyślną dla pola formularza w Symfony2?
Dodaj wartość domyślną do atrybutu danych podczas dodawania pola za pomocą elementu FormBuilder, dostosowanego na podstawie odpowiedzi Dmitriya.
Należy zauważyć, że zakłada się, że właściwość będzie i będzie miała wartość null tylko wtedy, gdy jest nową, a nie istniejącą jednostką.
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('color', 'text', array(
'label' => 'Color:',
'data' => (isset($options['data']) && $options['data']->getColor() !== null) ? $options['data']->getColor() : '#0000FF'
)
);
}
Możesz ustawić wartość domyślną, np. Dla formularza message
, w ten sposób:
$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
->add('name', 'text')
->add('email', 'email')
->add('message', 'textarea')
->add('send', 'submit')
->getForm();
W przypadku, gdy twój formularz jest mapowany na jednostkę, możesz przejść w ten sposób (np. Domyślna nazwa użytkownika):
$user = new User();
$user->setUsername('John Doe');
$form = $this->createFormBuilder($user)
->add('username')
->getForm();
Ogólne rozwiązanie dla każdego przypadku / podejścia, głównie poprzez użycie formularza bez klasy lub gdy potrzebujemy dostępu do jakichkolwiek usług, aby ustawić wartość domyślną:
// src/Form/Extension/DefaultFormTypeExtension.php
class DefaultFormTypeExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (null !== $options['default']) {
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($options) {
if (null === $event->getData()) {
$event->setData($options['default']);
}
}
);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('default', null);
}
public function getExtendedType()
{
return FormType::class;
}
}
i zarejestruj rozszerzenie formularza:
app.form_type_extension:
class: App\Form\Extension\DefaultFormTypeExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
Następnie możemy użyć default
opcji w dowolnym polu formularza:
$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
Nie używaj:
'data' => 'Default value'
Przeczytaj tutaj: https://symfony.com/doc/current/reference/forms/types/form.html#data
„Opcja danych zawsze zastępuje wartość pobraną z danych domeny (obiektu) podczas renderowania. Oznacza to, że wartość obiektu jest również zastępowana, gdy formularz edytuje już utrwalony obiekt, powodując utratę jego utrwalonej wartości po przesłaniu formularza.”
Użyj następujących:
Powiedzmy, że w tym przykładzie masz Entity Foo i istnieje pole „aktywne” (w tym przykładzie jest to CheckBoxType, ale proces jest taki sam jak w przypadku każdego innego typu), które chcesz domyślnie sprawdzić
W swojej klasie FooFormType dodaj:
...
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
...
public function buildForm( FormBuilderInterface $builder, array $options )
{
...
$builder->add('active', CheckboxType::class, array(
'label' => 'Active',
));
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event){
$foo = $event->getData();
// Set Active to true (checked) if form is "create new" ($foo->active = null)
if(is_null($foo->getActive())) $foo->setActive(true);
}
);
}
public function configureOptions( OptionsResolver $resolver )
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle:Foo',
));
}
'data' => $data['myfield'] ?? 'Default value'
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
if ($data == null) {
$form->add('position', IntegerType::class, array('data' => 0));
}
});
$event->setData()
zamiast czytania pola może sprawić, że będzie jeszcze lepiej.
Po prostu rozumiem problem.
Chcesz dostosować sposób tworzenia formularza na podstawie danych w Twojej encji. Jeśli jednostka jest tworzona, użyj wartości domyślnej. Jeśli jednostka istnieje, użyj wartości bazy danych.
Osobiście uważam, że rozwiązanie @ MolecularMans jest drogą do zrobienia. W rzeczywistości ustawiłbym wartości domyślne w konstruktorze lub w instrukcji właściwości. Ale wydaje się, że nie lubisz tego podejścia.
Zamiast tego możesz wykonać następujące czynności: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
Zawieszasz odbiornik na swoim typie formularza, a następnie możesz zbadać swoją jednostkę i dostosować kreatora-> odpowiednio dodać instrukcje w oparciu o to, czy masz nową lub istniejącą jednostkę. Nadal musisz gdzieś określić wartości domyślne, chociaż możesz je po prostu zakodować w swoim odbiorniku. Lub przekaż je do typu formularza.
Wydaje się jednak, że to dużo pracy. Lepiej jest po prostu przekazać jednostkę do formularza z ustawionymi już wartościami domyślnymi.
Często dla domyślnych wartości inicjalizacji formularza używam urządzeń. Oczywiście ten sposób nie jest najłatwiejszy, ale bardzo wygodny.
Przykład:
class LoadSurgeonPlanData implements FixtureInterface
{
public function load(ObjectManager $manager)
{
$surgeonPlan = new SurgeonPlan();
$surgeonPlan->setName('Free trial');
$surgeonPlan->setPrice(0);
$surgeonPlan->setDelayWorkHours(0);
$surgeonPlan->setSlug('free');
$manager->persist($surgeonPlan);
$manager->flush();
}
}
Jednak pole typu symfony ma dane opcji .
Przykład
$builder->add('token', 'hidden', array(
'data' => 'abcdef',
));
Jest bardzo prosty sposób, możesz ustawić wartości domyślne, jak tutaj:
$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);
$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
Jeśli ustawisz „dane” w formularzu tworzenia, ta wartość nie zostanie zmodyfikowana podczas edycji encji.
Moje rozwiązanie to:
public function buildForm(FormBuilderInterface $builder, array $options) {
// In my example, data is an associated array
$data = $builder->getData();
$builder->add('myfield', 'text', array(
'label' => 'Field',
'data' => array_key_exits('myfield', $data) ? $data['myfield'] : 'Default value',
));
}
PA.
'data' => $data['myfield'] ?? 'Default value',
Wartości domyślne są ustawiane przez skonfigurowanie odpowiedniej jednostki. Przed powiązaniem jednostki z formularzem ustaw jej kolor na „# 0000FF”:
// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);
Jeśli to pole jest powiązane z jednostką (jest właściwością tej jednostki), możesz po prostu ustawić dla niego wartość domyślną.
Przykład:
public function getMyField() {
if (is_null($this->MyField)) {
$this->setMyField('my default value');
}
return $this->MyField;
}
Zwykle po prostu ustawiam wartość domyślną dla określonego pola w mojej encji:
/**
* @var int
* @ORM\Column(type="integer", nullable=true)
*/
protected $development_time = 0;
To zadziała w przypadku nowych rekordów lub aktualizacji istniejących.
'empty_data'
wywołanie zwrotne jest używane, aby zezwolić na parametry konstruktora w jednostce.
Jak zapytał Brian:
Wydaje się, że empty_data ustawia pole na 1 tylko wtedy, gdy zostanie przesłane bez wartości. A co, jeśli chcesz, aby formularz wyświetlał domyślnie 1 w danych wejściowych, gdy nie ma żadnej wartości?
możesz ustawić wartość domyślną za pomocą empty_value
$builder->add('myField', 'number', ['empty_value' => 'Default value'])