In refference to my question I asked a few hours ago, I will try to ask more specific question now.
I have followed guidelines from official cookbook, and this article.
I have added new class MyType extends AbstractType in Me\MyBundle\Controller\Form\Type direcory.
I have created a template for that custom field type.
I have added proper entry in config.yml in order to use new template in forms.
But how can I use that custom field?
Let's say I have controller which looks like this:
namespace Me\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Me\MyBundle\Form\Type\MyType;
class DefaultController extends Controller
{
public function indexAction()
{
$form = $this->createFormBuilder()
->add('my_type', new MyType(), array('param' => 0))
->getForm()
;
return $this->render('MyBundle::index.html.twig', array(
'form' => $form->createView(),
));
}
}
Line ->add('my_type', new MyType(), array('param' => 0)) does not seem to have any affect on generating form. There is also no errors.
How can I make my custom field to be reused in the same form multiple times, with different params?
Edit:
MyType class looks like this:
class MyType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'param' => 1,
)
));
}
public function getParent()
{
return 'text';
}
public function getName()
{
return 'my_type';
}
}
May try to implements buildForm method :
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options
{
$builder->add(...);
}
Related
I would like to know how to pass my entity correctly and another variable in my createForm function ?
Let me explain, I would like to do this:
$repo = $em->getRepository('ProjectBundle:Organisation\Organisation');
$list = $repo->children($this->getUser()->getOrganisation());
$form = $this->createForm('ProjectBundle\Form\Robot\RobotType', array($entity,$list));
I need to pass to my FormType another variable, so I use a array directly.
My FormType:
<?php
namespace ProjectBundle\Form\Robot;
use ProjectBundle\Entity\Robot\Robot;
use ProjectBundle\Form\User\UserType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class RobotType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('serial_number')
->add('shell_color',ChoiceType::class,array(
'choices' => Robot::getArrayShellColor()
))
->add('tray1Color',ChoiceType::class,array(
'choices' => Robot::getTrayColor()
))
->add('tray2Color',ChoiceType::class,array(
'choices' => Robot::getTrayColor()
))
->add('tray3Color',ChoiceType::class,array(
'choices' => Robot::getTrayColor()
))
->add('hasBattery')
->add('volume')
->add('organisation',null,array('choices' => $options['data'][1]));
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'ProjectBundle\Entity\Robot\Robot'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'projectbundle_robot_new';
}
}
Here I need to get my variable $list, for the organisation field, so it's $options['data'][1].
But I have a mistake, which I understand but I do not know how to correct:
The form's view data is expected to be an instance of class ProjectBundle\Entity\Robot\Robot, but is a(n) array. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) array to an instance of ProjectBundle\Entity\Robot\Robot.
This is normal because now I pass it in an array, it's my variable $options['data'][0] that contains my object now.
How to do ?
Thank you
You should pass ProjectBundle\Entity\Robot\Robot entity to the createForm method as a second parameter and an options array as a third parameter.
$form = $this->createForm('ProjectBundle\Form\Robot\RobotType', $entity, array($list));
Ok it is probably something simple but i just cant find where the problem is.
I have tried with but no match for my problem
I am trying to create from but from form class, not create form in controller..
here is the code..
this is from controller
/**
* #Route("login", name="login")
*/
public function loginAction (Request $request) {
$registration = new Registration();
$form = $this->createForm(LoginForm::class, $registration, array(
'method' => 'POST'
));
return $this->render(
'admin/login.html.twig',
array('form' => $form->createView())
);
}
Inside controller i used USE to defind LoginForm i use in part createForm, so that is not problem
this is from FORM class
<?php
namespace AppBundle\AppForm;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class LoginForm extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('password')
->add('save', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'AppBundle\Entity\Registration'
));
}
public function getName()
{
}
}
Your problem in Symfony version. You use code from Symfony3 while really have Symfony2.
Change SubmitType::class to submit, LoginForm::class to new LoginForm() and all will work fine.
Or you can update your Symfony version and all will work fine with your current code.
tl;dr:
Is there any way to have the 'context' option auto-cascade through all form types ? It would NOT be leasable to pass it along manually in the form types like this:
$builder->add('organizer', 'organizer_type', array('context' => $options['context']));
Hello everybody,
I have written an extension to ALL Symfony form types:
class ContextExtension extends AbstractTypeExtension
{
protected $context;
public function __construct(SecurityContextInterface $context)
{
$this->context = $context->getToken()->getUser()->getContext();
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults([
'context' => $this->context
]);
$resolver->setAllowedTypes(['context' => 'GOC\Bundle\FrameworkBundle\Model\ContextInterface']);
}
/**
* Returns the name of the type being extended.
*
* #return string The name of the type being extended
*/
public function getExtendedType()
{
return 'form';
}
}
I have validated that it is registered and working (for the most part). I only face one problem. When I set my new option ('context') in a form type like this:
class EventType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'eventgroup', 'eventgroup_type', array(
'context' => $context,
)
)
}
public function getName()
{
return 'event';
}
}
I receive the option in the event group form type and can work with it there:
class EventGroupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->log($options['context']);
$builder
->add('name', 'text')
->add('comment', 'text')
->add('organizer', 'organizer_type')
;
}
public function getName()
{
return 'eventgroup_type';
}
}
However, it appears that the options does not cascade any further and is therefore not usable in the text or organizer type. Is there any way to have the 'context' option auto-cascade through all form types ? It would NOT be leasable to pass it along manually in the form types like this:
$builder->add('organizer', 'organizer_type', array('context' => $options['context']));
I am trying to build a form for multiple entities. Let me first introduce some sample classes:
For clarity I do not show all annotations or abbreviate them, and I do not show the use or namespace commands.
/**
* The Entity class
* #ORM ... mapping to ORM
*/
class EntityA {
/**
* #var ModelArray
* #ORM\Column(name="...", type="object")
*/
private $modelArray;
// Getters and Setters, default constructor
}
/**
* An array Wrapper, keeping the array always unique, sorting it by criteria etc.
* #ORM(...)
*/
class ModelArray {
/**
* #var array<A>
*/
private $array;
// Getter, Adder, Remover, Constructor, other private logic
}
Notice especially that the class ModelArray stores only objects of a given Type A:
/**
* One more Model
*/
class A {
/**
* #var boolean
*/
private $bool;
/**
* #var string
*/
private $string;
// Getters, Setters
}
I chose this data structure, because I never need objects of A to exist outside the EntityA class, and to keep the logic out of my Entity, I chose to implement the ModelArray class in between. The EntityA class is persisted to a database, and with it the child objects.
Now I want to create a form, where I can edit the $->bool attributes of all A instances of an Array of EntityA at once.
So what I provide is array<EntityA>.
I would then proceed as follows:
//In a controller action
$data = array(
'as' => $arrayOfEntityA,
);
$form = $this->createForm(new GridType(), $data);
// Create view, render
My form type would look like this:
class GridType extends AbstractType {
public function getName() {
return 'a_grid';
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('as', 'collection', array(
'type' => new GridAType(),
));
}
}
And use this form type
class GridAType extends AbstractType {
public function getName() {
return 'a_grid_a';
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('modelArray', new ModelArrayType());
}
public function getDefaultOptions(array $options) {
return array(
'data_class' => 'EntityA',
);
}
}
With the model array type
class ModelArrayType extends AbstractType {
public function getName() {
return 'model_array';
}
public function buildForm(FormBuilderInterface $builder, array $options) {
// ???
}
public function getDefaultOptions(array $options) {
return array(
'data_class' => 'ModelArray',
);
}
}
Notice the // ???: I would like to only edit the boolean attribute of the As strored in the ModelArray, and I think the appropriate form type to continue would be a 'collection'. But I can't really find out how to use the array ($modelArray->array)here as a collection.
How should I do this?
An then, I'm not entirely sure if it is good practice to implement such a lot of form types just to achieve one usable form. Is there a different and better way?
I have a question about service and Form in Symfony2,so I created my calss form and I hope to add a multiselect list of cities then I want to get list of cities from another class "city",so how I can call my class "city" in my form using "Service" to get a function "getcities" to return me a list of cities? (I dont use Doctrine here)...
Edit
namespace Acme\DemoBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CityType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'choices' => array( /**
* Here I will call function getcities(return list of cities)
*/
)
));
}
public function getParent()
{
return 'choice';
}
public function getName()
{
return 'gender';
}
}
class City.php :
Class City {
/**
* here i will get list of cities
*/
public function getcities()
{
.....
return $Listcities;
}
}
So I would like to use "Service" to call function "getcities" in form?
The form objects are not container-aware...at least, they're not meant to be. That said, your controller should use the service to get the cities, and then it should pass that list into the form object either through a constructor or a method.
Controller:
class SomethingController
{
public function someAction()
{
...
$cities = $this->get("citiesService")->getCities();
$form = $this->createForm(new SomeType($cities), $someEntity);
...
}
}
Form:
class SomeType extends AbstractType
{
private $cities;
public function __construct($cities)
{
$this->cities = $cities;
}
public function buildForm(FormBuilder $builder, array $options)
{
// Now you have access to $this->cities, so you can use it to build the form
}
}
Do you can set City object as form data object?
so it can looks like that...
$form = $this->createForm(new SomeType(), new City());
class SomeType extends AbstractType
{
public buildForm(FormBuilderInterface $builder, array $options)
{
$formFactory = $builder->getFormFactory();
$builder->addEventListener(
FormsEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formFactory) {
$event->getForm()->add(
$formFactory->createNamed(
'gender',
'choice',
null,
array(
'choices' => $event->getData()->getCites()
)
)
);
}
);
}
}