¿Hay una manera fácil de establecer un valor predeterminado para el campo de formulario de texto?
¿Hay una manera fácil de establecer un valor predeterminado para el campo de formulario de texto?
Respuestas:
Se puede usar fácilmente durante la creación con:
->add('myfield', 'text', array(
'label' => 'Field',
'empty_data' => 'Default value'
))
'data'
clave a'value'
empty_data
data
es inútil: sobrescribe el valor guardado. empty_data
no muestra el valor, lo usa en el envío de valor vacío y hace que sea imposible guardar las opciones sin marcar.
puede establecer el valor predeterminado con empty_data
$builder->add('myField', 'number', ['empty_data' => 'Default value'])
He contemplado esto varias veces en el pasado, así que pensé en anotar las diferentes ideas que tuve / usé. Algo puede ser útil, pero ninguna es una solución "perfecta" de Symfony2.
Constructor En la Entidad puede hacer $ this-> setBar ('valor predeterminado'); pero esto se llama cada vez que carga la entidad (db o no) y es un poco desordenado. Sin embargo, funciona para cada tipo de campo, ya que puede crear fechas o cualquier otra cosa que necesite.
Si las declaraciones dentro de get's no lo haría, pero tú podrías.
return ( ! $this->hasFoo() ) ? 'default' : $this->foo;
Fábrica / instancia . Llame a una función estática / clase secundaria que le proporciona una entidad predeterminada previamente rellenada con datos. P.ej
function getFactory() {
$obj = new static();
$obj->setBar('foo');
$obj->setFoo('bar');
return $obj;
}
No es realmente ideal dado que tendrá que mantener esta función si agrega campos adicionales, pero significa que está separando los establecedores de datos / predeterminados y lo que se genera a partir de la base de datos. Del mismo modo, puede tener múltiples getFactories si desea diferentes datos predeterminados.
Entidades extendidas / de reflexión Cree una entidad extendida (por ejemplo, FooCreate extiende Foo) que le proporciona los datos predeterminados en el momento de la creación (a través del constructor). Similar a la idea de Fábrica / instancia, solo un enfoque diferente: prefiero los métodos estáticos personalmente.
Establecer datos antes del formulario de compilación En los constructores / servicios, usted sabe si tiene una nueva entidad o si se completó desde la base de datos. Por lo tanto, es posible llamar a los datos del conjunto en los diferentes campos cuando se toma una nueva entidad. P.ej
if( ! $entity->isFromDB() ) {
$entity->setBar('default');
$entity->setDate( date('Y-m-d');
...
}
$form = $this->createForm(...)
Eventos de formulario Cuando crea el formulario, establece los datos predeterminados al crear los campos. Anula este uso del detector de eventos PreSetData. El problema con esto es que está duplicando la carga de trabajo del formulario / duplicando el código y haciendo que sea más difícil de mantener / comprender.
Formularios extendidos Similar a los eventos de formulario, pero llama a los diferentes tipos dependiendo de si es una entidad db / new Con esto quiero decir que tiene FooType que define su forma de edición, BarType extiende FooType esto y establece todos los datos en los campos. En su controlador, simplemente elija qué tipo de formulario instigar. Sin embargo, esto es una mierda si tienes un tema personalizado y te gustan los eventos, crea demasiado mantenimiento para mi gusto.
Ramita Puede crear su propio tema y predeterminar los datos utilizando la opción de valor también cuando lo hace por campo. No hay nada que lo detenga envolviendo esto en un tema de formulario si desea mantener sus plantillas limpias y el formulario reutilizable. p.ej
form_widget(form.foo, {attr: { value : default } });
JS Sería trivial llenar el formulario con una función JS si los campos están vacíos. Podría hacer algo con marcadores de posición, por ejemplo. Sin embargo, esta es una mala, mala idea.
Formularios como servicio Para uno de los grandes proyectos basados en formularios que hice, creé un servicio que generaba todos los formularios, realizaba todo el procesamiento, etc. Esto se debía a que los formularios debían usarse en múltiples controladores en múltiples entornos y mientras los formularios se generaron / manejaron de la misma manera, se mostraron / interactuaron de manera diferente (por ejemplo, manejo de errores, redirecciones, etc.). La belleza de este enfoque fue que puede predeterminar los datos, hacer todo lo que necesita, manejar los errores genéricamente, etc. y todo está encapsulado en un solo lugar.
Conclusión Tal como lo veo, te encontrarás con el mismo problema una y otra vez: ¿dónde están los datos predeterminados?
Con ese fin, he abordado el problema de manera diferente cada vez. Por ejemplo, una opción de "boletín" de formulario de suscripción se configura fácilmente (y lógicamente) en el constructor justo antes de crear el formulario. Cuando estaba creando colecciones de formularios que estaban vinculados entre sí (por ejemplo, qué botones de radio en diferentes tipos de formularios vinculados entre sí), entonces utilicé Event Listeners. Cuando construí una entidad más complicada (por ejemplo, una que requería hijos o muchos datos predeterminados), utilicé una función (por ejemplo, 'getFactory') para crear su elemento cuando lo necesito.
No creo que haya un enfoque "correcto" ya que cada vez que he tenido este requisito ha sido ligeramente diferente.
¡Buena suerte! Espero haberte dado algo de reflexión en cualquier caso y no divagar demasiado;)
Si necesita establecer el valor predeterminado y su formulario se relaciona con la entidad, entonces debe usar el siguiente enfoque:
// buildForm() method
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
...
->add(
'myField',
'text',
array(
'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
)
);
}
De lo contrario, myField
siempre se establecerá en el valor predeterminado, en lugar de obtener el valor de la entidad.
$options['data']->getMyField()
con$option['data']['myField']
empty_data
: Esta opción determina qué valor devolverá el campo cuando el valor enviado esté vacío. No establece un valor inicial
Puede establecer el valor predeterminado para el campo relacionado en su clase de modelo (en la definición de mapeo o establecer el valor usted mismo).
Además, FormBuilder le brinda la oportunidad de establecer valores iniciales con el método setData () . El generador de formularios se pasa al método createForm () de su clase de formulario.
Además, consulte este enlace: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class
Si su formulario está vinculado a una entidad, simplemente establezca el valor predeterminado en la entidad usando el método de construcción:
public function __construct()
{
$this->field = 'default value';
}
'mapped' => false
). Uso setData(...)
para estos.
Enfoque 1 (de http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/ )
Simplemente establezca el valor predeterminado en su entidad, ya sea en la declaración de variable o en el constructor:
class Entity {
private $color = '#0000FF';
...
}
o
class Entity {
private $color;
public function __construct(){
$this->color = '#0000FF';
...
}
...
}
Enfoque 2 de un comentario en el enlace anterior, y también la respuesta de Dmitriy (no la aceptada) de ¿Cómo establecer el valor predeterminado para el campo de formulario en Symfony2?
Agregue el valor predeterminado al atributo de datos al agregar el campo con FormBuilder, adaptado de la respuesta de Dmitriy.
Tenga en cuenta que esto supone que la propiedad tendrá y solo tendrá el valor nulo cuando se trata de una entidad nueva y no existente.
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'
)
);
}
Puede establecer un valor predeterminado, por ejemplo, para el formulario message
, como este:
$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
->add('name', 'text')
->add('email', 'email')
->add('message', 'textarea')
->add('send', 'submit')
->getForm();
En caso de que su formulario esté asignado a una Entidad, puede ir así (por ejemplo, nombre de usuario predeterminado):
$user = new User();
$user->setUsername('John Doe');
$form = $this->createFormBuilder($user)
->add('username')
->getForm();
Una solución general para cualquier caso / enfoque, principalmente mediante el uso de un formulario sin clase o cuando necesitamos acceso a cualquier servicio para establecer el valor predeterminado:
// 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;
}
}
y registre la extensión del formulario:
app.form_type_extension:
class: App\Form\Extension\DefaultFormTypeExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
Después de eso, podemos usar la default
opción en cualquier campo de formulario:
$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
No utilizar:
'data' => 'Default value'
Lea aquí: https://symfony.com/doc/current/reference/forms/types/form.html#data
"La opción de datos siempre anula el valor tomado de los datos de dominio (objeto) cuando se procesa. Esto significa que el valor del objeto también se anula cuando el formulario edita un objeto ya persistente, haciendo que pierda su valor persistente cuando se envía el formulario".
Use lo siguiente:
Digamos, para este ejemplo, tiene un Entity Foo, y hay un campo "activo" (en este ejemplo es CheckBoxType, pero el proceso es el mismo para cualquier otro tipo), que desea que se verifique de forma predeterminada
En su clase FooFormType agregue:
...
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()
lugar de leer el campo podría hacerlo aún mejor.
Solo para que entienda el problema.
Desea ajustar la forma en que se crea el formulario en función de los datos de su entidad. Si la entidad se está creando, utilice algún valor predeterminado. Si la entidad existe, use el valor de la base de datos.
Personalmente, creo que la solución de @ MolecularMans es el camino a seguir. De hecho, establecería los valores predeterminados en el constructor o en la declaración de propiedad. Pero no parece que te guste ese enfoque.
En su lugar, puede seguir esto: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
Cuelga un oyente en su tipo de formulario y luego puede examinar su entidad y ajustar el constructor-> agregar declaraciones en consecuencia en función de una entidad nueva o existente. Aún necesita especificar sus valores predeterminados en algún lugar, aunque podría codificarlos en su escucha. O páselos al tipo de formulario.
Sin embargo, parece mucho trabajo. Es mejor simplemente pasar la entidad al formulario con sus valores predeterminados ya establecidos.
A menudo, para los valores predeterminados de inicialización de la forma, uso fixtures. Por supuesto, este camino no es más fácil, pero sí muy cómodo.
Ejemplo:
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();
}
}
Sin embargo, el campo de tipo Symfony tiene los datos de la opción .
Ejemplo
$builder->add('token', 'hidden', array(
'data' => 'abcdef',
));
Hay una manera muy simple, puede establecer valores predeterminados como aquí:
$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);
$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
Si configura 'datos' en su formulario de creación, este valor no se modificará cuando edite su entidad.
Mi solución es:
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',
));
}
Adiós.
'data' => $data['myfield'] ?? 'Default value',
Los valores predeterminados se establecen configurando la entidad correspondiente. Antes de vincular la entidad a formar, configure su campo de color en "# 0000FF":
// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);
Si ese campo está vinculado a una entidad (es una propiedad de esa entidad), solo puede establecer un valor predeterminado para él.
Un ejemplo:
public function getMyField() {
if (is_null($this->MyField)) {
$this->setMyField('my default value');
}
return $this->MyField;
}
Por lo general, solo configuro el valor predeterminado para un campo específico en mi entidad:
/**
* @var int
* @ORM\Column(type="integer", nullable=true)
*/
protected $development_time = 0;
Esto funcionará para nuevos registros o si solo actualiza los existentes.
'empty_data'
se utiliza una devolución de llamada para permitir parámetros de constructor en la entidad.
Como Brian preguntó:
empty_data parece establecer solo el campo en 1 cuando se envía sin valor. ¿Qué sucede cuando desea que el formulario muestre de manera predeterminada 1 en la entrada cuando no hay ningún valor presente?
puede establecer el valor predeterminado con empty_value
$builder->add('myField', 'number', ['empty_value' => 'Default value'])