I have a problem, I want to create a simple search form with a filter assembly. These filters are attributes that belong to attribute groups.
group 1
[] Attribute 1
[] Attribute 2
[] Attribute 3
group 2
[] Attribute 1
[] Attribute 2
[] Attribute 3
But the problem is that I can not do (graphic aspect)
$builder->add('attribut', 'entity', array(
'class' => 'RestoFrontBundle:Attribut',
'group_by' => 'groupeAttribut.id',
'expanded' => true,
'multiple' => true,
'query_builder' => function(AttributRepository $er) {
return $er->createQueryBuilder('a')
->join("a.groupeAttribut", 'g')
->where("a.statut = 1");
}
))
->getForm();
Also I can not manage the game if the checkbox has been checked.
You note that the graphic aspect is the hard part. That is due to the way checkboxes are used in HTML. Unlike select inputs there is no notion of an optgroup. The closest analog for checkboxes would be a fieldset with a legend.
You may want explore using a Choice Field type rather than an entity type. Provide your choices via some provider function within which you format the options array(s) whether or not you retrieved them from a database. ( For the record, that's exactly how I populate the select at http://stayattache.com which has multiple places to retrieve options from. ) You may even want to explore creating your own form field type and template to format the output. Checkout the documentation on creating your own field type.
I hope that helps a bit. There are probably plenty of other ways to approach this as well.
Related
I am trying to set the label of an embedded form type (collection type).
These labels have to be different for the different collections.
For example I have two collections and an array with the labels ['label1','label2'] in die form type.
I think I need the index of the collection iteration to get the right label.
Like below i need the index for the entry_options label to get the right value of the $labels array.
Thats my buildForm Method
public function buildForm(FormBuilderInterface $builder, array $options)
{
$labels = ['label1', 'label2'];
$builder
->add('otherForms', CollectionType::class, [
'entry_type' => otherFormType::class,
'entry_options' => ['label' => $labels[$index]],
])
...
;
}
After reading your comments, I must agree that translation bundles are sometimes heavy weight and quite inconvenient.
The CollectionType usually ignores the index/key of collection items given to it, though.
Now I see two scenarios: you want to give the labels as an option to your form or the form shall be dependent on the data (using form events). Your code so far suggests, that languages are set globally and will not be added on the fly in some other manner.
In the first scenario it's very simple (see below), the second scenario requires some event listener in your form, but apart from that, it's quite similar.
The essential idea is to just create the forms you need (optionally inside the pre-submit handler), since you apparently already know which forms you need from the label array:
foreach($labels as $index => $label) {
$builder->add('otherForms'.$index, otherFormType::class, [
'label' => $label,
'property_path' => 'otherForms['.$index.']',
]);
}
The use of property_path will help you access the proper elements (however, changing the language (= key) of a translation might be difficult, but that should not happen, usually. And even if it happens, only some copy-pasta is necessary).
Your otherForms keys probably will be differently, but I guess you'll figure it out.
I have an entity Machine which has a relation MM with other entity Piece. The pieces can be from 3 different types. Currently the form Machine is built with a selection list in which the whole array collection Machine.pieces is fetched. My idea is to build 3 different selection lists with a subset of Machine.pieces each.
I have tried two different approaches but I have no been able to accomplish it.
Use a MachineRepository class where a method
public function findPiecesByPieceType($pieceTypeID)
returns the proper query->getResult().
Then I add a choiceType in MachineType but I am not able to populate it from MachineController. I have used $form->get('pieces')->setData($arrcollectPieces) and other methods to add choices but I always get error.
How could I add choices from the controller to a Form?
In the form I use a queryBuilder
->add('pieces', EntityType::class, array(
'label' => 'label_pieces',
'class' => 'AppBundle\Entity\Piece',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('p')
->where('p.pieceType = :pieceType')
->setParameter('pieceType', 1);
},
)
)
this works but when I try to add more queryBuilders (->add('pieces2'... and so on) I have the error because
Neither the property pieces2 nor one of the methods getPiecess2(), pieces2(), isPieces2(), hasPieces2(), __get() exist and have public access in class AppBundle\Entity\Machine.
How can I use the various queryBuilders not bounded to a method name in that way?
Maybe both approaches are incorrect and I should solve this in a different way?
(Posted on behalf of the OP).
How to make it using 1.
In MachineController forget setData(), instead turn the arrayCollection into 2 arrays (arKeys, arValues) and send them to the form as the 3rd parameter in createForm().
$form = $this->createForm(<type>, <data>,
array ('p_keys' => array(...), 'p_values' => array(...)));
From MachineType.ConfigureOptions() we can fetch them
$resolver->setDefined(["p_keys",'p_values']);
and they will be available in MachineType.buildForm()
$options['p_keys'];
$options['p_values'];
I have 3 tables:
Post -> Type -> Category
I need to get the category on the Post entity passing per Type to use this on a filter form
This is possible?
like a join and subjoin
If I understand correctly, you want to be able to filter Post's by Category.
Like with any other field you wish to filter by, you have to add a Form to the filter's FormBuilder. The problem in this case is that the Entity bound to the form doesn't have the property category. It's its property type who does.
Thus, you need to tell the Form how to access the right property. This is achieved by using the property_path option. Here's the documentation for it.
You would do something like this in your filter's Type:
$builder
->add('category', 'entity', array(
'label' => 'Category',
'data_class' => 'Category',
'property_path' => 'type.category',
))
;
The property_path option is very powerful. It will accept any path that the PropertyAccess component does. Read its documentation here.
Multiple joins are possible in doctrine. Please, read this section in doctrine documentation.
This is an existing schema I'm working with and I'm trying to not make any changes for the time being. I have an entity property that represents a university semester, like "fall12", "spring11", etc.
When adding or editing this entity with a form, I want to split that property into two form fields: "Season" (fall or spring") and "Year" (2011, 2012, etc):
...
->add('formSemesterSeason', 'choice', array(
'label' => 'Season',
'mapped' => false,
'choices' => array('fall' => 'Fall', 'spring' => 'Spring'),
))
->add('formSemesterYear', 'choice', array(
'label' => 'Year',
'mapped' => false,
'choices' => $this->courseManager->getYearChoices(),
))
...
When submitting the form, the values need to be combined and saved to the "semester" property on the entity as a string
When viewing the edit form, the existing "semester" value needs to be split between the two.
I don't think data transformers help here, since they apply to transforming just one form item.
Right now I'm using a form event POST_SET_DATA to fill out the two form fields when editing an existing entity:
$builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) use ($course_manager) {
$course = $event->getData();
$form = $event->getForm();
$semester = $course->getSemester();
$parsed_semester = $course_manager->parseSemesterMachineName($semester);
$form->get('formSemesterSeason')->setData($parsed_semester->season);
$form->get('formSemesterYear')->setData($parsed_semester->yearFull);
});
This works well, but how do I then combine the values back after the form has been submitted? I can do it easily in the controller, but I think I should be able to use form events, and have the data manipulation take place before form validation.
You can combine them back in a POST_SUBMIT listener.
The best way (reuseable) would be to create your own custom form type with a data transformer to split/combine the fields internally.
There are "recipes" in the cookbook but the best way that I found to create it was to rip apart the DateTime field type and associated transformers (DataTransformerChain, DateTimeToArrayTransformer & ArrayToPartsTransformer) for parts and build my own from that.
This is such a trivial problem that I can't believe I couldn't find an answer.
Symfony 2, doctrine 2.1. I've got two entities and one intermediate entity (join table). User, Pref, and UsersPrefs. Pref table is dictionary table, so that I could change pref name in one place only. Ok, let's see the picture:
infographic http://dl.dropbox.com/u/22495762/infographic.png
As You can see, I want to have a checkbox group, with all the possible choices (prefs) and preferred choices checked. So, if there are 3 prefs, and only 2 selected by the user, there should be 3 checkboxes, 2 selected.
It's simple, if done plain PHP - query database twice to get list of all prefs and user prefs, render checkboxes depending on values, add some actions to handle form submit, done.
But for the life of God I can't get this to work using symfony & doctrine. I was able to get to the point where I can update relationships in doctrine and further in database, but I'm using raw query values for that:
$data = $request->request->get('some_form');
and this supposedly isn't the way it should be done?
Morevoer, I'm completely stuck as to how should I display checkbox list. I either get list of all options, none checked, or only user options, all checked. Or 'left joined' result set with checkboxes for all cases, useless anyway.
I've come to the point where I tried to overload twig checkbox template, but I couldn't pass variables to the form template, and that was the last straw...
EDIT:
This way I'm getting group of checkboxes, not connected to user choices:
->add('prefs', 'entity', array(
'class' => 'Some\TestBundle\Entity\Pref',
'expanded' => 'true',
'multiple' => 'true',
'property' => 'name'
))
And this way I'm getting only user choices, all checked:
->add('prefs', 'entity', array(
'class' => 'Some\TestBundle\Entity\UserPrefs',
'multiple' => 'false',
'expanded' => 'false',
'property' => 'pref.name',
'query_builder' => function(EntityRepository $er) use ($id) {
return $er->createQueryBuilder('u')
->where("u.user = :id")
->setParameter('id', $id)
;
},
))
And I tried left joins and other options, but at best I could get list of all possible options for all possible users, checked accordingly.
EDIT (POSSIBLE SOLUTION):
I'm displaying checkbox group:
->add('pref_ids', 'choice', array(
'choices' => array(
'1' => 'pref one',
'2' => 'pref two',
'3' => 'pref three',
),
'expanded' => 'true',
'multiple' => 'true'
))
I've added $pref_ids array in User entity. Now I just need to set values in array according to preferences chosen by user:
public function setPrefIds()
{
$prefs = $this->getPrefs();
$this->pref_ids = array();
foreach($prefs as $pref){
array_push($this->pref_ids, $pref->getPref()->getId());
}
return $this;
}
This way I get appropriate checkboxes checked.
Writing values to database is reversal of the process. I'm getting input values from request:
$data = $request->request->get('edit_form');
var_dump($data['pref_ids']);
Removing all user prefs:
foreach ($userPrefs as $pref){
$em->remove($pref);
}
And setting actual associations in doctrine from ids:
$entity->setPrefsById($em, $data['pref_ids']);
Here I'm passing entity manager to entity itself, but I need to refactor it, because it looks kinda messy this way.
Then $em->flush(); and that's it.
That's the best I could come up with. Probably it's overcomplicated and should be done entirely different way. Unfortunately couldn't figure out this "other way".
You need the choice field type: http://symfony.com/doc/current/reference/forms/types/choice.html
In your builder, it will be something like
$builder->add('prefs', 'choice', array('multiple' => true, 'expanded' => true, 'choices' => fetch the available prefs from the database here);
Edit: Sorry I'm mistaken, you need the "Entity" type, which fetches automatically the choices from the database: http://symfony.com/doc/current/reference/forms/types/entity.html
You must still put multiple => true expanded => true to get checkboxes.