How and when to use createForm vs createFormBuilder - forms

I am working with Symfony 3.4 and wonder how and when to use createForm vs createFormBuilder
In my case I need to create two different forms for the same data class, e.g. an user object User. The forms only differ in some additional fields.
For example one registration form for normal users with additional fields to accept the legal terms, subscribe to the newsletter, etc. And one registration form for admin users with some other additional fields. In both cases the same User class is used and the additional fields are not mapped:
public function regUserAction(Request $request) {
// Create and show user reg form
}
public function regAdminAction(Request $request) {
// Create and show admin reg form
}
Since the User form is needed/used in two different places it would be good idea to create a UserFormType and create the form using createForm
public function regUserAction(Request $request) {
$form = $this->createForm(UserFormType::class, $user, array());
}
public function regAdminAction(Request $request) {
$form = $this->createForm(UserFormType::class, $user, array());
}
class UserFormType extends AbstractType {
// setup of form fields, FormEvents handlers, etc.
}
Pro: The setup of the form has to implemented only once in UserFormType
Con: It is not possible to add custom fields to the created form, in regUserAction and regAdminAction, is it?
Since the User form needs to be customized it would be a good idea to use createFormBuilder instead:
public function regUserAction(Request $request) {
$formBuilder = $this->createFormBuilder($user, array())
->add(... common form setup ...)
->add(... custom user fields ...)
}
public function regAdminAction(Request $request) {
$formBuilder = $this->createFormBuilder($user, array())
->add(... common form setup ...)
->add(... custom admin fields ...)
}
Pro: Possible to add custom fields to the form
Con: Common setup of the form has to be implemented again for each form.
Is there any way to mix these two approaches? To implement the common form setup only once AND to add custom fields per form?

You can modify the form in the FormType using FormEvents like described here in the Symfony Docs. There is an example modifying a form based on user data.

Maybe you can implement the code in a service and return the $formBuilder object to customise it in your actions. Or you can implement a sort of factory pattern and build your $formBuilder based on the params you will pass to it.

Related

EasyAdmin 3 create custom field

I'd like to create custom autocomplete field with externe api call.
I'm using doc Create custom fields
But my template is not used.
public static function new(string $propertyName, ?string $label = null): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
// this template is used in 'index' and 'detail' pages
->setTemplatePath('admin/field/address.html.twig')
// this is used in 'edit' and 'new' pages to edit the field contents
// you can use your own form types too
->setFormType(TextType::class)
->addCssClass('field-address')
// these methods allow to define the web assets loaded when the
// field is displayed in any CRUD page (index/detail/edit/new)
->addCssFiles('js/admin/field-address.css')
->addJsFiles('js/admin/field-address.js')
;
}
I've no error.
I create template in : /templates/admin/field
Anyone has an idea ?

Reuse Zend 2 form with captcha for editing

I have a form for some element creation with captcha.
It works fine.
But I want use this form in Admin page too, and there should be no captcha.
When I try to submit form I have an error
["captcha"] => array(1) {
["isEmpty"] => string(36) "Value is required and can't be empty"
}
How can I reuse this form without captcha? Is there another method without extending another new form?
Solved.
Just create Filter
use Zend\InputFilter\Input;
use Zend\InputFilter\InputFilter;
class FreeLessonFilter extends InputFilter
{
public function __construct()
{
$this->addElements();
}
protected function addElements()
{
$captcha = new Input('captcha');
$captcha->setRequired(TRUE);
$this->add($captcha);
}
}
And than use it in Admin page controller, but not in Index page
$this->defaultForm = new FreeLessonForm();
$filter = new FreeLessonFilter();
$filter->get('captcha')->setRequired(false);
$this->defaultForm->setInputFilter($filter);
By default it required, but in admin - not.

mapping the data of the child form on the parent form symfony2

I have created a Form Type that adds an autocomplete feature for Entities, however it requires some configuration for every Entity, i.e: I have to pass the configuration to the options array, so I decided to make a new FormType for each Entity using the AutoCompleteType I created and reuse them.However I want these Formtypes i.e: the ones for each particular Entity, to return the Entity when getData() is called on it, what happens now is that I have to first retrieve the field of ParentForm containing the AutoCompleteType then call getData() to retrieve my Entity.How can I map this information directly on the ParentForm?
//the FormType of Some Entity using the AutoComplete
...
class SomeEntityAutoCompleteType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array options){
$builder->add('some_entity', 'entity_autocomplete', array(...));
}
}
//the controller
public function someAction(){
$form = $this->get('form.factory')->create(new SomeEntityAutoCompleteType());
...
//I want the below line to return my entity
$form->getData();
//but I have to use this one right now
$form['some_entity']->getData()
}
note: I haven't actually tested the other approach but from what I understand of the Symfony Form Component it should be the way I described;
I solved it by setting the parent type of my SomeEntityAutoCompleteType to the main autocomplete type I had created and configuring the options using the setDefaultOptions() method.
//SomeEntityAutoCompleteType
public function setDefaultOption(OptionsResolverInterface $resolver){
$resolver->setDefaults(...);
}
public function getParent(){
return "autocomplete_type";//this is the main autocomplete type I mentioned
}

ZF2 layout form set input filters and validation

For my application in Zend Framework 2 I created a 'search form' in my layout.phtml.
I did this in my Application module by adding the search form as an variable.
(Form location Application/src/Application/Form/SearchForm.php)
Application/Module.php:
public function setFormToView($e)
{
$searchForm = new SearchForm();
$viewModel = $e->getViewModel();
$viewModel->setVariables(array(
'searchForm' => $searchForm,
));
}
The form directs to an Action in another module, here I want to handle what to do with
the incoming query.
MyModule/src/MyModule/Controller/MyModuleController.php
public function dataAction()
{
$form = new SearchForm();
$form->get('submit')->setValue('Add');
$website = $this->params()->fromQuery('search');
return array('searchForm', $form);
}
Getting the query 'search' is no problem, it works well. No I want to use my inputFilter I created under 'Application/src/Application/Model/Search.php'.
I tried to add this in my 'dataAction()' but no results, but I even can't change the submit value as I tried in my example above.
How do I set this in the right way in this situation? Or else, what is the right situation to handle a search form in layout.phtml.
Thanks in advance,
Nick

Symfony: How to hide form fields from display and then set values for them in the action class

I am fairly new to symfony and I have 2 fields relating to my table "Pages"; created_by and updated_by. These are related to the users table (sfGuardUser) as foreign keys. I want these to be hidden from the edit/new forms so I have set up the generator.yml file to not display these fields:
form:
display:
General: [name, template_id]
Meta: [meta_title, meta_description, meta_keywords]
Now I need to set the fields on the save. I have been searching for how to do this all day and tried a hundred methods. The method I have got working is this, in the actions class:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form_params = $request->getParameter($form->getName());
$form_params['updated_by'] = $this->getUser()->getGuardUser()->getId();
if ($form->getObject()->isNew()) $form_params['created_by'] = $this->getUser()->getGuardUser()->getId();
$form->bind($form_params, $request->getFiles($form->getName()));
So this works. But I get the feeling that ideally I shouldnt be modifying the web request, but instead modifying the form/object directly. However I havent had any success with things like:
$form->getObject()->setUpdatedBy($this->getUser()->getGuardUser());
If anyone could offer any advice on the best ways about solving this type of problem I would be very grateful.
Thanks,
Tom
After processing and saving the form you could set those fields on the object and re-save:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()));
if ($form->isValid())
{
$page = $form->save();
$user = $this->getUser()->getGuardUser();
$page->setUpdatedBy($user);
if (empty($page->created_by))
{
$page->setCreatedBy($user);
}
$page->save();
$this->getUser()->setFlash('notice', 'Successfully saved page.');
$this->redirect('#homepage');
}
}
There's also a Doctrine extension called Blameable that automatically sets edited_by and created_by fields on specified models. The Doctrine website is undergoing some reorganization but here is the cached page for the extension.
To process your form create a new object, set the fields then save.
$article = new Article();
$article->setName($request->getParameter($form->getName());
$article->setDescription($request->getParameter($form->getDescription());
$article->setMetaKeywords($request->getParameter($form->getMetaKeywords());
$article->save();
What you want to do is customize your form and unset the 'created_at' and 'updated_at' pieces of the form in configure
class SampleForm extends BaseSampleForm
{
public function configure()
{
unset(
$this['created_at'],
$this['updated_at']
);
}
}
Then they won't show up in the form and will get the values setup by the "Timestampable" behavior before being saved
http://stereointeractive.com/blog/2010/04/07/symfony-forms-hide-created_at-updated_at-columns/