C'è un modo semplice per impostare un valore predefinito per il campo del modulo di testo?
C'è un modo semplice per impostare un valore predefinito per il campo del modulo di testo?
Risposte:
Può essere utilizzato durante la creazione facilmente con:
->add('myfield', 'text', array(
'label' => 'Field',
'empty_data' => 'Default value'
))
'data'
chiave in'value'
empty_data
data
è inutile: sovrascrive il valore salvato. empty_data
non mostra il valore, lo usa su invio di valore vuoto e rende impossibile salvare le scelte non selezionate.
puoi impostare il valore predefinito con empty_data
$builder->add('myField', 'number', ['empty_data' => 'Default value'])
L'ho contemplato alcune volte in passato, quindi ho pensato di annotare le diverse idee che avevo / usato. Qualcosa potrebbe essere utile, ma nessuna è la soluzione "perfetta" di Symfony2.
Costruttore Nell'entità è possibile eseguire $ this-> setBar ('valore predefinito'); ma questo viene chiamato ogni volta che carichi l'entità (db o no) ed è un po 'disordinato. Funziona tuttavia per ogni tipo di campo in quanto è possibile creare date o qualsiasi altra cosa sia necessaria.
Se le dichiarazioni all'interno di get non lo farei, ma potresti.
return ( ! $this->hasFoo() ) ? 'default' : $this->foo;
Fabbrica / istanza . Chiama una funzione statica / classe secondaria che ti fornisce un'entità predefinita precompilata con i dati. Per esempio
function getFactory() {
$obj = new static();
$obj->setBar('foo');
$obj->setFoo('bar');
return $obj;
}
Non proprio l'ideale dato che dovrai mantenere questa funzione se aggiungi campi aggiuntivi, ma significa che stai separando i setter di dati / default e quello che viene generato dal db. Allo stesso modo puoi avere più getFactories se desideri diversi dati predefiniti.
Entità estese / di riflessione Crea un'entità estesa (ad esempio FooCreate estende Foo) che ti fornisce i dati predefiniti al momento della creazione (tramite il costruttore). Simile all'idea di fabbrica / istanza, solo un approccio diverso: preferisco personalmente i metodi statici.
Imposta i dati prima del modulo di compilazione Nei costruttori / servizi, sai se hai una nuova entità o se è stata popolata dal database. È plausibile quindi chiamare i dati impostati sui diversi campi quando si prende una nuova entità. Per esempio
if( ! $entity->isFromDB() ) {
$entity->setBar('default');
$entity->setDate( date('Y-m-d');
...
}
$form = $this->createForm(...)
Eventi modulo Quando si crea il modulo, si impostano i dati predefiniti durante la creazione dei campi. Sostituisci questo listener di eventi PreSetData. Il problema è che stai duplicando il carico di lavoro del modulo / duplicando il codice e rendendo più difficile la manutenzione / comprensione.
Moduli estesi Simile agli eventi Modulo, ma si chiama il tipo diverso a seconda che si tratti di una nuova entità / db. Con questo intendo che hai FooType che definisce il tuo modulo di modifica, BarType estende FooType e imposta tutti i dati sui campi. Nel tuo controller scegli semplicemente quale tipo di modulo installare. Questo fa schifo se hai un tema personalizzato e come eventi, crea troppa manutenzione per i miei gusti.
Ramoscello Puoi creare il tuo tema e predefinire i dati usando anche l'opzione value quando lo fai in base al campo. Non c'è nulla che ti impedisca di avvolgerlo in un tema di modulo o se desideri mantenere i tuoi modelli puliti e il modulo riutilizzabile. per esempio
form_widget(form.foo, {attr: { value : default } });
JS Sarebbe banale popolare il modulo con una funzione JS se i campi sono vuoti. Ad esempio, potresti fare qualcosa con i segnaposto. Questa è una cattiva, cattiva idea però.
Moduli come servizio Per uno dei grandi progetti basati su moduli che ho realizzato, ho creato un servizio che ha generato tutti i moduli, eseguito tutte le elaborazioni, ecc. Questo perché i moduli dovevano essere utilizzati su più controller in più ambienti e mentre i moduli sono stati generati / gestiti allo stesso modo, sono stati visualizzati / interagiti in modo diverso (ad es. gestione degli errori, reindirizzamenti ecc.). La bellezza di questo approccio è che puoi impostare dati predefiniti, fare tutto ciò di cui hai bisogno, gestire errori genericamente ecc. Ed è tutto incapsulato in un unico posto.
Conclusione A mio modo di vedere, incontrerai più volte lo stesso problema: dove devono risiedere i dati predefiniti?
A tal fine, ho affrontato il problema in modo diverso ogni volta. Ad esempio, un'opzione di "newsletter" del modulo di iscrizione è facilmente (e logicamente) impostata nel costruttore appena prima di creare il modulo. Quando stavo costruendo raccolte di moduli che erano collegate tra loro (ad es. Quali pulsanti di opzione in diversi tipi di modulo collegati insieme) allora ho usato gli ascoltatori di eventi. Quando ho costruito un'entità più complicata (ad esempio una che richiedeva figli o molti dati predefiniti) ho usato una funzione (ad esempio 'getFactory') per crearne l'elemento di cui ho bisogno.
Non credo che esista un approccio "giusto", poiché ogni volta che ho avuto questo requisito è stato leggermente diverso.
In bocca al lupo! Spero di averti dato un po 'di spunti di riflessione in ogni caso e non ho fatto troppe cose;)
Se è necessario impostare il valore predefinito e il modulo è correlato all'entità, è necessario utilizzare il seguente approccio:
// buildForm() method
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
...
->add(
'myField',
'text',
array(
'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
)
);
}
In caso contrario, myField
verrà sempre impostato sul valore predefinito, anziché ottenere il valore dall'entità.
$options['data']->getMyField()
con$option['data']['myField']
empty_data
: Questa opzione determina quale valore restituirà il campo quando il valore inviato è vuoto. Non imposta un valore iniziale
È possibile impostare il valore predefinito per il campo correlato nella classe del modello (nella definizione della mappatura o impostare il valore manualmente).
Inoltre, FormBuilder ti dà la possibilità di impostare i valori iniziali con il metodo setData () . Il generatore di moduli viene passato a createForm () metodo della classe del modulo.
Inoltre, controlla questo link: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class
Se il modulo è associato a un'entità, basta impostare il valore predefinito sull'entità stessa utilizzando il metodo di costruzione:
public function __construct()
{
$this->field = 'default value';
}
'mapped' => false
). Utilizzare setData(...)
per questi.
Approccio 1 (da http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/ )
Basta impostare il valore predefinito nell'entità, nella dichiarazione della variabile o nel costruttore:
class Entity {
private $color = '#0000FF';
...
}
o
class Entity {
private $color;
public function __construct(){
$this->color = '#0000FF';
...
}
...
}
Approccio 2 da un commento nel link sopra, e anche la risposta di Dmitriy (non quella accettata) da Come impostare il valore predefinito per il campo modulo in Symfony2?
Aggiungi il valore predefinito all'attributo data quando aggiungi il campo con FormBuilder, adattato dalla risposta di Dmitriy.
Si noti che ciò presuppone che la proprietà avrà e avrà il valore null solo quando si tratta di un'entità nuova e non esistente.
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'
)
);
}
È possibile impostare un valore predefinito, ad esempio per il modulo message
, in questo modo:
$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
->add('name', 'text')
->add('email', 'email')
->add('message', 'textarea')
->add('send', 'submit')
->getForm();
Nel caso in cui il tuo modulo sia mappato su un'entità, puoi andare così (es. Nome utente predefinito):
$user = new User();
$user->setUsername('John Doe');
$form = $this->createFormBuilder($user)
->add('username')
->getForm();
Una soluzione generale per qualsiasi caso / approccio, principalmente utilizzando un modulo senza una classe o quando è necessario accedere a qualsiasi servizio per impostare il valore predefinito:
// 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;
}
}
e registra l'estensione del modulo:
app.form_type_extension:
class: App\Form\Extension\DefaultFormTypeExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
Successivamente, possiamo usare l' default
opzione in qualsiasi campo del modulo:
$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
Non usare:
'data' => 'Default value'
Leggi qui: https://symfony.com/doc/current/reference/forms/types/form.html#data
"L'opzione data sostituisce sempre il valore preso dai dati del dominio (oggetto) durante il rendering. Ciò significa che anche il valore dell'oggetto viene sostituito quando il modulo modifica un oggetto già persistente, causando la perdita del valore persistente quando viene inviato il modulo."
Utilizza il seguente:
Diciamo, per questo esempio, hai un Entity Foo, e c'è un campo "attivo" (in questo esempio è CheckBoxType, ma il processo è lo stesso per ogni altro tipo), che vuoi controllare per impostazione predefinita
Nella tua classe FooFormType aggiungi:
...
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()
invece di leggere il campo potrebbe renderlo ancora migliore.
Solo così capisco il problema.
Si desidera modificare il modo in cui il modulo viene creato in base ai dati nell'entità. Se l'entità viene creata, utilizzare un valore predefinito. Se l'entità è esistente, utilizzare il valore del database.
Personalmente, penso che la soluzione di @ MolecularMans sia la strada da percorrere. Vorrei effettivamente impostare i valori predefiniti nel costruttore o nella dichiarazione di proprietà. Ma non sembra che ti piaccia questo approccio.
Invece puoi seguire questo: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
Appendi un listener al tuo tipo di modulo e puoi quindi esaminare la tua entità e regolare il builder-> aggiungi le istruzioni di conseguenza in base al fatto che hai un'entità nuova o esistente. Devi ancora specificare i valori predefiniti da qualche parte, anche se potresti semplicemente codificarli nel tuo listener. Oppure passali nel tipo di modulo.
Sembra un sacco di lavoro però. Meglio semplicemente passare l'entità al modulo con i suoi valori predefiniti già impostati.
Spesso, per i valori di default di init del modulo, utilizzo i dispositivi. Di causa in questo modo non è più semplice, ma molto comodo.
Esempio:
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();
}
}
Tuttavia, il campo del tipo symfony ha i dati dell'opzione .
Esempio
$builder->add('token', 'hidden', array(
'data' => 'abcdef',
));
C'è un modo molto semplice, puoi impostare i valori predefiniti come qui:
$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);
$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
Se si impostano "dati" nel modulo di creazione, questo valore non verrà modificato quando si modifica l'entità.
La mia soluzione è:
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',
));
}
Ciao.
'data' => $data['myfield'] ?? 'Default value',
I valori predefiniti vengono impostati configurando l'entità corrispondente. Prima di associare l'entità al modulo impostare il campo di colore su "# 0000FF":
// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);
Se quel campo è associato a un'entità (è una proprietà di quell'entità) puoi semplicemente impostare un valore predefinito per essa.
Un esempio:
public function getMyField() {
if (is_null($this->MyField)) {
$this->setMyField('my default value');
}
return $this->MyField;
}
Di solito imposto il valore predefinito per un campo specifico nella mia entità:
/**
* @var int
* @ORM\Column(type="integer", nullable=true)
*/
protected $development_time = 0;
Questo funzionerà per i nuovi record o semplicemente aggiornando quelli esistenti.
'empty_data'
viene utilizzato un callback per consentire i parametri del costruttore sull'entità.
Come ha chiesto Brian:
empty_data sembra impostare il campo su 1 solo quando viene inviato senza valore. Che dire di quando si desidera che il modulo venga visualizzato per impostazione predefinita 1 nell'input quando non è presente alcun valore?
puoi impostare il valore predefinito con empty_value
$builder->add('myField', 'number', ['empty_value' => 'Default value'])