I am rendering a form, and every widget has an ID like : form_username, form_password, etc
and every corresponding label has a for field as for="form_username"
can I customize this ID and For attribute pair? Because I am rendering 2 forms on a page, and their field names are clashing...
edit : Here is an example code where I want to customize the Form Name.
$form = $this->createFormBuilder($user, array('validation_groups' => array('registration')))
->add('username', 'text')
->add('email', 'email')
->add('password', 'repeated', array('type' => 'password'))
->getform();
You need to provide different names for the forms when you create them in your controller:
$builder1 = $this->get('form.factory')->createNamedBuilder(new FooFormType(), 'foo1');
$builder2 = $this->get('form.factory')->createNamedBuilder(new FooFormType(), 'foo2');
Related
I've been struggling to get this done. In the docs, there doesn't seem to have any option to order a form field.
So, I have firstname and lastname fields in my form like this:
->add('firstname', TextType::class, [
'required' => true
])
->add('address', TextareaType::class, [
'required' => true
])
Then, I added an event listener like so:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$plan = $event->getData();
$form = $event->getForm();
if (!$plan->getReferenceId()) {
$form->add('ref', TextType::class, [
'label' => 'Reference Number',
'required' => true,
// position should be after the firstname and before address
]);
}
}
In some of the threads, there was a 'position' attribute that you can add but that was for Symfony 2 and that doesn't exist now in S4.
I guess this can be done in twig form_widget but I am using twig templates which is used in other forms as well. So I am hoping to get this done in the formtype if possible.
it seems to be a really required issue on Symfony github
here: https://github.com/symfony/symfony/issues/5827
and here: https://github.com/symfony/symfony/pull/11241#issuecomment-288462731 where Fabien personaly declined the possible solution on PR
i have the same problem and it seems that the only solution is order the fields manually printing them with form_row or form_widget one by one on the templates.
like this: https://symfony.com/doc/current/form/form_customization.html
So what is the best way to have a form render effectively the same form over and over again, with conditionally disabled fields based on the Entity's property values?
I have an Invoice Entity and need a form for creating the invoice, and also the same form with various fields disabled at various stages of the invoicing process (generated, sent, paid etc).
I think the simplest answer is to disable them dynamically in the twig template via form_row options but surely this will affect server side validation of the form as it is not aware the field has been disabled?
What is the best way to disbale a field based on a value in the database?
EDIT 1:
Changed question from Dynamically disable a field in the twig template or seperate class for each form? to Symfony4 Forms - How do you conditionally disable a form field?
Thanks to #Cerad. The answer is in fact Form Events
In the form type (App\Form\InvoicesType for me), add a method call to the end of the builder:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$plus_thirty_days = new \DateTime('+28 days');
$builder
->add('client', EntityType::class, array(
'class' => Clients::class,
'choice_label' => 'name',
'disabled' => false,
) )
// the event that will handle the conditional field
->addEventListener(
FormEvents::PRE_SET_DATA,
array($this, 'onPreSetData')
);;
}
and then in the same class, create a public method named the same as the string in the array (onPreSetData for this example):
public function onPreSetData(FormEvent $event)
{
// get the form
$form = $event->getForm();
// get the data if 'reviewing' the information
/**
* #var Invoices
*/
$data = $event->getData();
// disable field if it has been populated with a client already
if ( $data->getClient() instanceof Clients )
$form->add('client', EntityType::class, array(
'class' => Clients::class,
'choice_label' => 'name',
'disabled' => true,
) );
}
From here you can update the field to be any valid FormType and specify any valid options as you would a normal form element in the From Builder and it will replace the previous one, laving it in the same original position in the form.
I am overriding the register page (overriding the Customer object) ; I have added "Type", which is a ChoiceType expanded (3 radio buttons), and I have added the defaultAddress fields (in which I have added 3 fields).
When I display the form, all these fields have a red star to show there are required, but when I submit the form, if I don't put anything in these fields, the form is submitted anyway and I have a database error because these fields are empty.
Here is my code :
CustomerRegistrationTypeExtension.php :
$builder->add('type', ChoiceType::class, [
'choices' => array('Particulier' => Customer::TYPE_PARTICULIER, 'Professionnel' => Customer::TYPE_PRO, 'Projet à but non lucratif' => Customer::TYPE_PROJET),
'expanded' => true,
'label' => 'Vous êtes',
'choice_attr' => array('onclick' => 'alert(\"click\")')
])
->add('siren', TextType::class)
->add('denomination', TextType::class)
->add('defaultAddress', AddressType::class);
AddressTypeExtension.php
$builder->add('showOnMap', CheckboxType::class)
->add('geocodeLat', HiddenType::class)
->add('geocodeLng', HiddenType::class);
_address.html.twig :
{{ form_row(form.showOnMap, {'label' : 'address.showMap.label'}) }}
{{ form_row(form.geocodeLat)}}
{{ form_row(form.geocodeLng)}}
_form.html.twig
{{ form_row(form.type) }}
Any idea ?
Thanks !
Red asterisk near the field is just an UI feature. To require some fields, you must specify theirs validation configuration. Check out Symfony validation documentation to get required info, all of it should perfectly work in Sylius ;)
One important thing - remember to set sylius in groups parameter when defining constraints, it is a default validation group in Sylius.
i find this snippet useful indeed to put a default value in my form while creating it
$builder
->add('myfield', 'text', array(
'label' => 'Field',
'data' => 'Default value'))
;
what if i want to replace 'default value' with an authentified person from the FOSUser bundle? ( that return true to is_granted("IS_AUTHENTICATED_REMEMBERED"))
i can retrieve that name on a twig file with
{{ app.user.username }}
i have also done it in a controller method with
$username=$this->container->get('security.context')->getToken()->getUser()->getUsername()
but i can't manage to make this working in my form!
i am not sure i understand that container thing well ...neither how to transfer variables betweenn classes and controller...
something around this maybe??
->add('myfield', 'text', array(
'label' => 'Field',
'data' => FOS\UserBundle\Model::$this->getUsername()))
You can passe variable from your controller to your form :
in your controller :
$username=$this->container->get('security.context')->getToken()->getUser()->getUsername()
$form = $this->createForm(new MyFormType($username), $entity);
in your form :
protected $username;
public function __construct (array $username = null)
{
$this->username = $username ;
}
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('myfield', 'text', array(
'label' => 'Field',
'data' => $this->username))
}
Another way to set default values into a form is to set them on the underlying data object for the form, as in this example from the Symfony documentation on building a form:
public function newAction()
{
// create a task and give it some dummy data for this example
$task = new Task();
$task->setTask('Write a blog post');
$task->setDueDate(new \DateTime('tomorrow'));
$form = $this->createFormBuilder($task)
->add('task', 'text')
->add('dueDate', 'date')
->getForm();
return $this->render('AcmeTaskBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
In this example, the form's underlying data object is a Task and the values set on the task are the default values to be displayed in the form. The task object is not persistent. This approach works just as well with a form class and assuming the underlying object for your form is a User would look something like this:
$username = $this->container->get('security.context')->getToken()->getUser()->getUsername();
$user = new User();
$user->setUsername($username);
// could set any other default values on user here
$form = $this->createForm(new MyFormClass(), $user);
The disadvantage of this approach is if the form is used in many places requiring the same defaults the code would be repeated. This is not a situation I've come across so far - my User forms are re-used for create/edit but edit doesn't require the defaults.
I need to set default values for my form. There is code, from my controller:
$form = $this->createFormBuilder()->add('user', new Form\UserType($user))
->add('client', new Form\ClientType($client))
->getForm();
And I have two entites: User & Client. So, how I can set default values from entites?
I set the default values for my text fields like this
->add('firstname', 'text', array('attr' => array('value' => 'bla')))
for an Entity you can set empty value to false and fill the prefrred_choices array
->add('language', 'entity', array('empty_value' => false, 'preferred_choices' => array('2'), 'class' => 'CPAppUserBundle:Language', ))
In the form classes of each your user and your client class you can set default values like this:
public function configure() {
$this->setDefault('yourfield', $defaultvalue);
}