Symfony Forms - entity field with query_builder, no choices_as_values? - forms

I am trying to achieve something very simple but not sure if this is supported, possible or unexpected behaviour. I have a Symfony entity field which loads some data based on the selection of another field. The data is loaded ok but I want the option name and value to be the same. At the moment, it is populating the names ok, but I want the values to be the same as the names (the choices_as_values option in a Symfony choice field). Is that possible in an entity field.
Here is an example code:
$builder
->addEventListener(
Form\FormEvents::POST_SET_DATA,
function (Form\FormEvent $event) {
$attributeData = $event->getData();
$event->getForm()->add(
'group',
'entity',
array(
'class' => 'AppBundle:CategoryAttributeData',
'placeholder' => 'Select a data group',
'label' => 'Attribute Group',
'choice_label' => 'content',
'required' => false,
'query_builder' => function (Repository\CategoryAttributeData $repository) use ($attributeData) {
$queryBuilder = $repository->createQueryBuilder('u')
->select('u')
->where('u.type = :type')
->andWhere('u.group IS NULL')
->setParameter('type', $attributeData->getType())
;
return $queryBuilder;
}
)
);
}
)
;
The output is:
<select id="attribute_data_group" name="attribute_data[group]" class="form-control">
<option value="">Select a data group</option>
<option value="1">Cars</option>
<option value="2">Electronics</option>
<option value="3">Furniture</option>
</select>
What I am trying to achieve is:
<select id="attribute_data_group" name="attribute_data[group]" class="form-control">
<option value="">Select a data group</option>
<option value="Cars">Cars</option>
<option value="Electronics">Electronics</option>
<option value="Furniture">Furniture</option>
</select>
Since this field is populated via an event listener (because it depends on another field value) I cannot add a view transformer in here.
Any suggestions?

This is actually more complicated than it would seem on the surface. The Entity form type assumes that the "values" of the choice selector are the unique identifier for an entity, this allows the form type (and its associated transformers) to find and transform the passed values from and to the relevant entities. So the first question is - can you uniquely identify your entity by the string "Cars", or "Electronics"? If you can't, then the next question is how were you planning on converting that string into the entity?
If you can, then things are relatively easier. Effectively you need to provide a different ChoiceList implementation for the choice field type - this is effectively what the Entity type already does. I'm not familiar with the correct way to do this and I believe the method changed between Symfony 2.6 and 2.7, but I would look into classes like Symfony\Bridge\Doctrine\Form\Type\EntityType as well as the base Symfony\Component\Form\Extension\Core\Type\ChoiceType.
Short version: it's not wholly straightforward but definitely possible.

It can be done with the option 'choice_value', for example:
'choice_value' => function (?Team $team) {
return $team ? $team->getBesoccerId() : '';
}
It's 100% compatible with the 'query_builder' option. Continuing the same example:
->add('team', EntityType::class, array(
'class' => Team::class,
'label' => 'Equipo',
'query_builder' => function (EntityRepository $er) use ($lang) {
return $er->createQueryBuilder('t')
->andWhere('t.besoccerId IS NOT NULL')
->andWhere('i18n.cod_lang = :cod_lang')
->setParameter('cod_lang', $lang)
->leftJoin('t.translations', 'i18n')
->orderBy('t.sort', 'ASC');
},
'choice_label' => 'name',
'choice_value' => function (?Team $team) {
return $team ? $team->getBesoccerId() : '';
}
))
You can find more information in the documentation.

Related

Empty option in a form query symfony 3.4

I must display an entity in a query_builder form
here is my code in the form type:
$builder->add('dispositif', EntityType::class, array(
'class' => 'LeaPrestaBundle:EgwDispositif',
'label' => 'nomDispositif',
'required' => true,
'empty_data' => null,
'query_builder' => function( $er)
{
return $er->createQueryBuilder('d')
->where('d.isActive = :isActive')
->setParameter('isActive', 1 )
->orderBy('d.nomDispositif','ASC');
},
));
The problem is that the option is empty :
<select id="egw_presta_dispositif" name="egw_presta[dispositif]">
<option value="52"></option>
<option value="55"></option>
<option value="62"></option>
<option value="58"></option>
</select>
For example, aside the value 52, there should have a label for "dispositif" (name of dispositif).
Does it coming from the entity ?
Thanks in advance for your help!
Try adding a 'choice_label' property with the EgwDispositif field containing what you want to display:
$builder->add('dispositif', EntityType::class, array(
'class' => 'LeaPrestaBundle:EgwDispositif',
/** label will be displayed next to your form field unless it's a translation key or else **/
'label' => 'Nom du dispositif',
'required' => true,
'empty_data' => null,
/** any field containing what you want to display as option label **/
'choice_label' => 'nomDispositif',
'query_builder' => function( $er)
{
return $er->createQueryBuilder('d')
->where('d.isActive = :isActive')
->setParameter('isActive', 1 )
->orderBy('d.nomDispositif','ASC');
},
));
It seems like you were confusing the option 'label' of the form field property with the option 'choice_label' . You probably want your label to be something user will read (bu maybe not, it's up to you)
take a look here : https://symfony.com/doc/current/reference/forms/types/entity.html

Trying to get property of non-object - Laravel Form

I am creating a form with a many-many relationship. I have a posts table and an activities table. There is a many to many link using pivot table. I am creating a form to add one or more activities to the posts. I am receiving an 'ErrorException' - Trying to get property of non-object. I cannot understand why this is not working.
I would be grateful for any assistance you can offer me.
My relevant code is below.
//Posts/create.blade.php
{!!Form::open(['action' => 'PostController#store','method' => 'POST', 'class'=>'form-group'])!!}
{{Form::bsText('title','',['placeholder' => 'Trip Name'])}}
{{Form::bsTextarea('body','',['placeholder' => 'Trip Description'])}}
{{Form::bsSubmit('submit')}}
{{Form::label('activities', 'Activity:') }}
<select class="form-control select2-multi" name="activities" multiple="multiple">
#foreach($activities as $activity)
<option value="{{ $activity->id }}">{{ $activity->activity_name}}
</option>
#endforeach
</select>
{!! Form::close() !!}
// PostsController
public function create()
{
$activities = Activity::all();
return view('posts.create')->withActivities($activities);
$posts = Post::all();
}
public function store(Request $request)
{
// Create a new post using the request data
// Save it to the database
$this->validate(request(), [
'title' => 'required',
'body' => 'required',
]);
$post = Post::create([
'title' =>request('title'),
'body' =>request('body'),
'user_id' => auth()->id(),
'activity_id' => id()
]);
// And then redirect to somewhere in application
return redirect()->route('posts.show', $post->id);
}
This error throw only when you have empty variable but you point in blade file to render / display for browser. Or if you retrieve records from DB then add findOrFail in query to prevent those kind of issues. Thank you.

EntityType's choice_value is removing duplicate values

Im trying to build a select html element populated with database entities. I need the labels and values in the select element to be drawn from non-default entity values, so I use the 'choice_label' and 'choice_value' options.
The problem is that any entities with duplicate 'choice_value' (territory) values are being removed (replaced?).
Here's my form builder:
$builder->add('country', EntityType::class, array(
'class' => 'AcmeCheckoutBundle:Country',
'label' => 'Country',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('c')
->orderBy('c.name', 'ASC');
},
'choice_label' => 'name',
'choice_value' => 'territory'
));
This is what I expect:
<select>
<option value="1">United Kingdom</option>
<option value="2">France</option>
<option value="2">Germany</option>
<option value="3">Brazil</option>
<option value="3">Canada</option>
</select>
This is what I'm getting:
<select>
<option value="1">United Kingdom</option>
<option value="2">Germany</option>
<option value="3">Canada</option>
</select>
If I remove 'choice_value' from the form builder I get all the records but obviously with the wrong values.
Prior symfony3 array of choices for ChoiceType has folowing structure:
$choices = [
'value1' => 'label1',
'value2' => 'label2', ...
];
So when you fill this array with your elements, elements with duplicate values are overwritten. Since symfony2.7 array of choices was reworked, now it has inversed structure:
$choices = [
'label1' => 'value1',
'label2' => 'value2', ...
];
Now you can have duplicate values, but must have unique labels. This structure was introduced in symfony2.7 but is not enabled by default and is used by default in symfony3.
To enable this structure in symfony2.7 you can use option choices_as_values (http://symfony.com/doc/2.7/reference/forms/types/choice.html#choices-as-values).
Actually this option is not mentioned in EntityType symfony documentation, but as EntityType extends ChoiceType it should work. If it is not, you can use ChoiceType instead od EntityType and provide choices manually.

Drupal 7 - Construct clean URL from form post

I am creating a custom module in Drupal 7 that is a job search. I am wanting to make it so you can specify a clean URL to perform the search like so:
www.example.com/job-board/cardiology/california
Where "cardiology" is the "specialty" variable and "california" is the "location" variable.
now I know how to do this as far as mapping the variables in my hook_menu and accessing the variables. The problem is how do I create a search form that creates the clean url when you submit it? In other words if I had this:
<form method="get" action="job-board">
<select name="specialty">
<option value="cardiology">Cardiology</option>
<option value="some_other_value">Some Other Value</option>
</select>
<select name="location">
<option value="california">California</option>
<option value="some_other_state">Some Other State</option>
</select>
<input type="submit">
</form>
and I submit it, it will go to www.example.com/job-board?specialty=cardiology&location=california instead of www.example.com/cardiology/california. How can I make the form construct a clean URL?
You should create that form using Drupal's Form API and assign a custom submit callback to it.
In that submit callback, you can perform validation and if everything is OK, redirect the user to the appropriate URL.
See the source code of Examples modules, specifically one related to Form API in order to learn more about it.
In short, here's what you would do:
/**
* Sample form.
*/
function MYMODULE_sample_form() {
$form['specialty'] = array(
'#title' => t('Specialty'),
'#type' => 'textfield',
'#required' => TRUE,
);
$form['state'] = array(
'#title' => t('State'),
'#type' => 'select',
'#options' => array(
'california' => t('California')
),
);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Submit the form'));
return $form;
}
/**
* Sample form submit processing.
*/
function MYMODULE_sample_form_submit($form, &$form_state) {
$specialty = $form_state['values']['specialty'];
$state = $form_state['values']['state'];
drupal_goto($specialty . '/ ' . $state);
}

Symfony2 - How to customize the select option labels for the entity field type when using the query_builder?

When i create an entity field in Symfony2, how i can specify the value of the select option-field generated ?
This is the snippet of my entity field:
->add('preferred_language', 'entity', array(
'mapped' => false,
'property' => 'name',
'class' => 'Common\MainBundle\Entity\Language',
'query_builder' => function(\Doctrine\ORM\EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.id', 'DESC');
}
Actually i can specify the shown value through the property and it takes automatically the id referred to the db table. Good. What can i do, instead, whether i want to change the option value?
<option value="my_value">my_property</option>
If you create an "entity" field, you create a relation form between two entities, so the default field value is the id annoted field on your entity.
You can change this behavior with a View Transformer. Check out this doc:
http://symfony.com/doc/current/cookbook/form/data_transformers.html#model-and-view-transformers
also looked for same solution and found it here: different property for entity field type in form
just set the property in the field type options and create a getter for the property that formats the string the way to output the label.
I solved it by the following way:
code in FormType must be the same:
->add('preferred_language', 'entity', array(
'mapped' => false,
'property' => 'name',
'class' => 'Common\MainBundle\Entity\Language',
'query_builder' => function(\Doctrine\ORM\EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.id', 'DESC');
}
In the controller, I get the data with DQL:
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery('SELECT u FROM MyBundle:Language ORDER BY u.id DESC');
$data = $query->getResult();
I pass the data through render method:
return $this->render('MyBundle:Default:page.html.twig',
array('formulario' => $formulario->createView(),
'data' => $data));
In the twig file, I create a <select> item with id "myproject_mybundle_myformtype_preferred_language":
<select id="myproject_mybundle_myformtype_preferred_language" name="aeneagrama_adminbundle_itemcontenidotype[preferred_language]" class="form-control">
<option value="0">-- Choose an option --</option>
{% for item in data %}
<option value="{{ item.your_column }}">{{ item.name }}</option>
{% endfor %}</select>
Finally, when you get input data from the form, you can get it in the controller:
$form->get('preferred_language')->getData();
In your controller make this change,
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery('SELECT u FROM MyBundle:Language u ORDER BY u.id DESC');
$data = $query->getResult();