I'm trying to unset a field before saving it, exactly in the executeCreate() function generated by sf. I'm using this:
$this->configuration->getForm()->getWidgetSchema()->offsetUnset('clients');
var_dump($this->configuration->getForm()->getWidgetSchema());
But after that the field "clients" is still there:
object(sfWidgetFormSchema)[180]
protected 'formFormatters' =>
array
empty
protected 'fields' =>
array
'id' =>
object(sfWidgetFormInputHidden)[211]
protected 'parent' =>
&object(sfWidgetFormSchema)[180]
protected 'requiredOptions' =>
array
...
protected 'attributes' =>
array
...
protected 'options' =>
array
...
'name' =>
object(sfWidgetFormInputText)[212]
protected 'parent' =>
&object(sfWidgetFormSchema)[180]
protected 'requiredOptions' =>
array
...
protected 'attributes' =>
array
...
protected 'options' =>
array
...
'clients' =>
object(sfWidgetFormInputText)[184]
protected 'parent' =>
&object(sfWidgetFormSchema)[180]
protected 'requiredOptions' =>
array
...
protected 'attributes' =>
array
...
protected 'options' =>
array
...
'_csrf_token' =>
object(sfWidgetFormInputHidden)[203]
protected 'parent' =>
&object(sfWidgetFormSchema)[180]
protected 'requiredOptions' =>
array
...
protected 'attributes' =>
array
...
protected 'options' =>
array
...
Any idea?
sf 1.4
Javi
You can unset form fields at form class, method configure:
class ClientsForm extends BaseClientsForm
{
public function configure()
{
unset($this['field1'], $this['field2']);
}
}
This removes field from form and from SQL query generated for saving this form
Related
I have come across a solution that filters fields from a resource collection in the Controller CompanyController.php
E.g The code below returns all the values except company_logo
CompanyResource::collection($companies)->hide(['company_logo']);
CompanyResource.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class CompanyResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected $withoutFields = [];
public static function collection($resource)
{
return tap(new CompanyResourceCollection($resource), function ($collection) {
$collection->collects = __CLASS__;
});
}
// Set the keys that are supposed to be filtered out
public function hide(array $fields)
{
$this->withoutFields = $fields;
return $this;
}
// Remove the filtered keys.
protected function filterFields($array)
{
return collect($array)->forget($this->withoutFields)->toArray();
}
public function toArray($request)
{
return $this->filterFields([
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'telephone' => $this->telephone,
'company_logo' => $this->company_logo,
'social_links' => $this->social_links,
]);
}
}
Now from my UserResource I still want to specify fields I don't want returned from the same CompanyResource but it's not a collection anymore in the UserResource
UserResource.php
public function toArray($request)
{
return [
'id' => $this->id,
'email' => $this->email,
'status' => $this->status,
'timezone' => $this->timezone,
'last_name' => $this->last_name,
'first_name' => $this->first_name,
'tags' => TagResource::collection($this->whenLoaded('tags')),
'company' => new CompanyResource($this->whenLoaded('company')),
];
}
So my idea is to be able to specify excluded fields on 'company' => new CompanyResource($this->whenLoaded('company')), Been stuck here for some time.
After researching I found a working solution for my problem
'company' => CompanyResource::make($this->whenLoaded('company'))->hide(['company_logo']),
Instead of the below which I could not use flexibly use:
'company' => new CompanyResource($this->whenLoaded('company')),
For some unknown reason, the EntityType form field will not display the selected option on submit, even though the name of the column matches and data passes.
I've created a form that I'm using to select some values that will filter a list of products.
<?php namespace AppBundle\Filter;
use AppBundle\Entity\ProductCategory;
use AppBundle\Repository\ProductCategoryRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ProductFilterType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', null, [
'required' => false,
'label' => 'SKU'
])
->add('productCategory', EntityType::class,
array(
'class' => ProductCategory::class,
'choice_label' => 'name',
'choice_value' => 'id',
'placeholder' => '',
'label_attr' => array('title' => 'Category for this product'),
'query_builder' => function (ProductCategoryRepository $v) {
return $v->createQueryBuilder('v')
->orderBy('v.name',' ASC');
}
))
->add('name', null, [
'required' => false,
])
->add('description', null, [
'required' => false,
])
;
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'app_bundle_product_filter_type';
} }
The form renders as expected, and it submits a post to the same URL, which filters based on the value received from the request.
That works ok.
However, when the form is re-rendered, the option that was selected before the form filter submission is no longer selected. All other inputs are repopulating.
I did notice that when I'm working with a form that is bound to an Entity (ie: Editting and saving the entity) and using the ConfigureOptions method to set the data class, that the EntityType form field works as expected. However, I need it to work in this case where the overall form is not bound to an Entity.
EDIT:
Doing these steps worked for me...but it seems a bit odd.
Injected entity manager into the form constructor:
public $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
Then updated the EntityType form field to get the object based on the array value:
->add('productCategory', EntityType::class,
array(
'class' => ProductCategory::class,
'choice_label' => 'name',
'choice_value' => 'id',
'placeholder' => '',
'label_attr' => array('title' => 'Category for this product'),
'data' => $this->em->getReference("AppBundle:ProductCategory",
isset($options['data']['productCategory']) ? $options['data']['productCategory'] : 0),
'query_builder' => function (ProductCategoryRepository $v) {
return $v->createQueryBuilder('v')
->orderBy('v.name',' ASC');
}
))
...
Another solution is using a Data Transformer.
Remove the data attribute from the productCategory type, and add a data transformer to the end of the build method:
$builder->get('productCategory')
->addModelTransformer(new CallbackTransformer(
function ($id) {
if (!$id) {
return;
}
return $this->em->getRepository('AppBundle:ProductCategory')->find($id);
},
function($category) {
return $category->getId();
}
));
If you use the same transformer in multiple places, you can extract it into its own class.
My workaround was like this ...
pass data and entity manager to formType.
$form = $this->createForm(new xxxType($this->get('doctrine.orm.entity_manager')), xxxEntity, array(
'method' => 'POST',
'action' => $this->generateUrl('xxxurl', array('id' => $id)),
'selectedId' => xxxId,
));
setDefaultOptions in form Type initialize as an empty array for selectedId
$resolver->setDefaults(array(
'data_class' => 'xxx',
'selectedId' => array()
));
and in builder
->add('productCategory', EntityType::class,
array(
'class' => ProductCategory::class,
'choice_label' => 'name',
'choice_value' => 'id',
'placeholder' => '',
'label_attr' => array('title' => 'Category for this product'),
'query_builder' => function (ProductCategoryRepository $v) {
return $v->createQueryBuilder('v')
->orderBy('v.name',' ASC');
},
'data'=>$this->em->getReference("xxx",$options['selectedId'])
))
for more details, you can see this answer Symfony2 Setting a default choice field selection
Heads up - I've already been here. Strange issue with Symfony3 forms. So I've created FormType class:
class GetPostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->setMethod("POST")
->add('phrase', Type\TextType::class);
}
}
As you can see form is not bound to any entity or other object(this shouldn't matter though). Now when I try to handle incoming request with that form:
$postForm = $this->createForm(GetPostType::class);
$postForm->handleRequest($this->request);
... normally handleRequest should submit my form. However:
$postForm->isSubmitted();
is false.
I've tracked down source of issue to HttpFoundationRequestHandler.
} elseif ($request->request->has($name) || $request->files->has($name)) {
According to this my form name is not present in request. That's what I don't get. I'm using Symfony forms at work and there's no problem. I used them in different projects and it was ok. Now for some reason I can't get them to work. It is probably something obvious but I guess I need another pair of eyes to see it.
As you can see I did try to set form method manually(it should be POST by default) but it didn't work. I did clear the cache and stuff. I did try different things I found on the internet but no luck.
I can't find anything that might be the reason. Any ideas what it might be?
UPDATE:
As requested in comments section I provide dump of my request object.
So how do I know it is the right thing? It is accepted by handleRequest method witch expects request type and it contains correct data.
/var/www/story/src/CodeCraft/BlogBundle/Controller/Api/PostController.php:73:
object(Symfony\Component\HttpFoundation\Request)[49]
public 'attributes' =>
object(Symfony\Component\HttpFoundation\ParameterBag)[12]
protected 'parameters' =>
array (size=4)
'_controller' => string 'CodeCraft\BlogBundle\Controller\Api\PostController::getPostsAction' (length=66)
'_route' => string 'blog.api.posts.get' (length=18)
'_route_params' =>
array (size=0)
...
'_firewall_context' => string 'security.firewall.map.context.main' (length=34)
public 'request' =>
object(Symfony\Component\HttpFoundation\ParameterBag)[10]
protected 'parameters' =>
array (size=1)
'phrase' => string 'xxx' (length=3)
public 'query' =>
object(Symfony\Component\HttpFoundation\ParameterBag)[11]
protected 'parameters' =>
array (size=0)
empty
public 'server' =>
object(Symfony\Component\HttpFoundation\ServerBag)[15]
protected 'parameters' =>
array (size=34)
'HTTP_CACHE_CONTROL' => string 'no-cache' (length=8)
'HTTP_POSTMAN_TOKEN' => string '2eea2285-a2f7-4ca5-a799-ea97758d7d20' (length=36)
'CONTENT_TYPE' => string 'application/x-www-form-urlencoded' (length=33)
'HTTP_USER_AGENT' => string 'PostmanRuntime/6.1.6' (length=20)
'HTTP_ACCEPT' => string '*/*' (length=3)
'HTTP_HOST' => string 'story.dev' (length=9)
'HTTP_ACCEPT_ENCODING' => string 'gzip, deflate' (length=13)
'CONTENT_LENGTH' => string '10' (length=2)
'HTTP_CONNECTION' => string 'keep-alive' (length=10)
'PATH' => string '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' (length=60)
'SERVER_SIGNATURE' => string '<address>Apache/2.4.18 (Ubuntu) Server at story.dev Port 80</address>
' (length=70)
'SERVER_SOFTWARE' => string 'Apache/2.4.18 (Ubuntu)' (length=22)
'SERVER_NAME' => string 'story.dev' (length=9)
'SERVER_ADDR' => string '192.168.33.10' (length=13)
'SERVER_PORT' => string '80' (length=2)
'REMOTE_ADDR' => string '192.168.33.1' (length=12)
'DOCUMENT_ROOT' => string '/var/www/story/web' (length=18)
'REQUEST_SCHEME' => string 'http' (length=4)
'CONTEXT_PREFIX' => string '' (length=0)
'CONTEXT_DOCUMENT_ROOT' => string '/var/www/story/web' (length=18)
'SERVER_ADMIN' => string 'webmaster#localhost' (length=19)
'SCRIPT_FILENAME' => string '/var/www/story/web/app_dev.php' (length=30)
'REMOTE_PORT' => string '57039' (length=5)
'GATEWAY_INTERFACE' => string 'CGI/1.1' (length=7)
'SERVER_PROTOCOL' => string 'HTTP/1.1' (length=8)
'REQUEST_METHOD' => string 'POST' (length=4)
'QUERY_STRING' => string '' (length=0)
'REQUEST_URI' => string '/app_dev.php/posts' (length=18)
'SCRIPT_NAME' => string '/app_dev.php' (length=12)
'PATH_INFO' => string '/posts' (length=6)
'PATH_TRANSLATED' => string '/var/www/story/web/posts' (length=24)
'PHP_SELF' => string '/app_dev.php/posts' (length=18)
'REQUEST_TIME_FLOAT' => float 1509896560.734
'REQUEST_TIME' => int 1509896560
public 'files' =>
object(Symfony\Component\HttpFoundation\FileBag)[14]
protected 'parameters' =>
array (size=0)
empty
public 'cookies' =>
object(Symfony\Component\HttpFoundation\ParameterBag)[13]
protected 'parameters' =>
array (size=0)
empty
public 'headers' =>
object(Symfony\Component\HttpFoundation\HeaderBag)[16]
protected 'headers' =>
array (size=10)
'cache-control' =>
array (size=1)
...
'postman-token' =>
array (size=1)
...
'content-type' =>
array (size=1)
...
'user-agent' =>
array (size=1)
...
'accept' =>
array (size=1)
...
'host' =>
array (size=1)
...
'accept-encoding' =>
array (size=1)
...
'content-length' =>
array (size=1)
...
'connection' =>
array (size=1)
...
'x-php-ob-level' =>
array (size=1)
...
protected 'cacheControl' =>
array (size=1)
'no-cache' => boolean true
protected 'content' => null
protected 'languages' => null
protected 'charsets' => null
protected 'encodings' => null
protected 'acceptableContentTypes' => null
protected 'pathInfo' => string '/posts' (length=6)
protected 'requestUri' => string '/app_dev.php/posts' (length=18)
protected 'baseUrl' => string '/app_dev.php' (length=12)
protected 'basePath' => null
protected 'method' => string 'POST' (length=4)
protected 'format' => null
protected 'session' =>
object(Symfony\Component\HttpFoundation\Session\Session)[5070]
protected 'storage' =>
object(Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage)[5071]
protected 'bags' =>
array (size=2)
...
protected 'started' => boolean false
protected 'closed' => boolean false
protected 'saveHandler' =>
object(Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy)[5090]
...
protected 'metadataBag' =>
object(Symfony\Component\HttpFoundation\Session\Storage\MetadataBag)[5065]
...
private 'flashName' => string 'flashes' (length=7)
private 'attributeName' => string 'attributes' (length=10)
protected 'locale' => null
protected 'defaultLocale' => string 'en' (length=2)
private 'isHostValid' => boolean true
private 'isClientIpsValid' => boolean true
private 'isForwardedValid' => boolean true
The actual field that would be rendered by your form is named get_post[phrase], not just phrase. Submitting get_post[phrase] in postman will work.
If you don't want that naming scheme you can override the getBlockPrefix method in your Form, eg:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class GetPostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('phrase', TextType::class);
}
public function getBlockPrefix()
{
return null;
}
}
I have the need to create a dropdown field with grouped data:
My form:
class RetailerDetailFilterType extends AbstractType
{
public function getActiveRetailerMetrics(): array
{
return range(25,36);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('month', EntityType::class,
[
'class' => 'AppBundle:ConsolidatedOperatorCategoryLowData',
'query_builder' => function(ConsolidatedOperatorCategoryLowDataRepository $er){
return $er->getMinMaxByMetricQueryBuilder($this->getActiveRetailerMetrics());
}
]);
}
public function getBlockPrefix()
{
return 'key_metric';
}
}
My Repository:
class ConsolidatedOperatorCategoryLowDataRepository extends \Doctrine\ORM\EntityRepository
{
public function getMinMaxByMetricQueryBuilder($metricRange)
{
$qb = $this->getEntityManager()
->createQueryBuilder('d');
$qb
->select('d.id, YEAR(d.date) as dyear, MONTH(d.date) as dmonth')
->from('AppBundle:ConsolidatedOperatorCategoryLowData','d')
->where($qb->expr()->in('d.metric_id', $metricRange))
->groupBy('dyear')
->addGroupBy('dmonth')
->setMaxResults(10)
;
return $qb;
}
I'm getting
Warning: spl_object_hash() expects parameter 1 to be object, integer given
at UnitOfWork ->isScheduledForInsert (3182005)
in vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 710 +
at EntityManager ->contains (3182005)
in vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php at line 116 +
at IdReader ->getIdValue (3182005)
at call_user_func (array(object(IdReader), 'getIdValue'), 3182005)
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php at line 205 +
at ArrayChoiceList ->flatten (array('id' => 3182005, 'dyear' => '2016', 'dmonth' => '12'), array(object(IdReader), 'getIdValue'), array(), array(), null)
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php at line 200 +
at ArrayChoiceList ->flatten (array(array('id' => 3182005, 'dyear' => '2016', 'dmonth' => '12'), array('id' => 3186685, 'dyear' => '2017', 'dmonth' => '1'), array('id' => 3191365, 'dyear' => '2017', 'dmonth' => '2'), array('id' => 3195595, 'dyear' => '2017', 'dmonth' => '3'), array('id' => 3200275, 'dyear' => '2017', 'dmonth' => '4')), array(object(IdReader), 'getIdValue'), array(), array(), array(null))
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php at line 91
I think it has to do with how Doctrine ORM deals with relationships. When you want to retrieve an entity by a referenced object's id, say find all posts by a user id, then you still have to pass the User-object to the QueryBuilder, not just the id. This is because Doctrine will resolve how those entities are connected itself.
It seems that metric_id actually is a reference to some kind of Metric-entity and just passing an array of int instead of the actual objects seems to trip up Doctrine's QueryBuilder.
You could try mapping the id's to a new instance of Metric and then pass that array instead.
Another solution - the one I would prefer - is to use Native SQL for this.
I am confronted to a problem that is driving me crazy for more than 3 days and I do not find any solutions. Nevertheless I found a post on stackoverflow that is EXCACTLY the problem I am facing. Unfortunately the person did manage to find a solution on his down but he or she did not shared it fully. As he explained it perfectly let just copy paste it here below:
By the way it seems that person who created that post only created his account for this problem and never came back since for other things. That it is why I allow myself to ask here again...
I have 2 entities (A and B) with a Many to One relationship between
them.
I create my form with the A entity and i use an entity field (dropdown
list) to display the rows in the B entity. I use a query builder to
filter them. If don't change the values in the list (ie. with ajax),
everything is working fine.
But if I change dynamicly the values in the dropdown, when I submit
the form I have this error "This value is invalid"
It's because the submitted value isn't included in the "array"
returned by the query builder.
It seems that this validation is automatic in symfony for entity field
(I don't use any asserts on this field). I'd like to get rid of this.
But how ?
It seems that I need to implement Form Events. Unfortunatally I do not get it. I read the documentation which is very poor on that subject, read a lot of posts, searched on the Internet but did not found anything.
Here below my personal form type. What I do is the following. I create the first entity field type with the mapped property set to false and filter the entity just to get the departements. Then I create another entity type called localisation. By default I filter the entity to get nothing (''). What I do then to populate it is to use Jquery. But unfortunatelly I am confro,ted to the same problem as the other buddy (see above).
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use Doctrine\ORM\EntityRepository;
use Auth\GeoBundle\Form\LocalisationType;
class RegistrationFormType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->add('departement', 'entity', array(
'mapped' => false,
'empty_value' => '',
'class' => 'AuthGeoBundle:Localisation',
'property' => 'departement',
'query_builder' => function ($repository) {
return $repository
->createQueryBuilder('e')
->add('groupBy', 'e.departement')
;
},
));
$builder->add('localisation', 'entity', array(
'empty_value' => '',
'class' => 'AuthGeoBundle:Localisation',
'property' => 'formLabel',
'query_builder' => function ($repository) use ($dpt) {
return $repository
->createQueryBuilder('e')
->where('e.departement = :dpt')
->setParameter('dpt', '')
->add('orderBy', 'e.ville ASC')
;
},
));
//some other fields here...
}
public function getName()
{
return 'auth_user_registration';
}
}
I finally manage to find a solution using the form events. I played with the "tutorial" at http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html and got it working :) Here below the code I used in case somebody interested.
My formType:
<?php
//src/Auth/UserBundle/Form/Type/RegistrationFormType.php
namespace Auth\UserBundle\Form\Type;
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use Doctrine\ORM\EntityRepository;
use Auth\GeoBundle\Form\LocalisationType;
use Auth\UserBundle\Form\EventListener\IsAdminFieldSubscriber;
class RegistrationFormType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
//NE PAS EFFACER -> exempled e comment ajouter un champ qui n'a rien à voir avec nos entitys
//$builder->add("firstName", "text", array("mapped" => false));
$builder->add('departement', 'genemu_jqueryselect2_entity', array(
'mapped' => false,
'empty_value' => '',
'class' => 'AuthGeoBundle:Localisation',
'property' => 'departement',
'query_builder' => function ($repository) {
return $repository
->createQueryBuilder('e')
->add('groupBy', 'e.departement')
;
},
));
$dpt = "";
$builder->add('localisation', 'genemu_jqueryselect2_entity', array(
'empty_value' => '',
'class' => 'AuthGeoBundle:Localisation',
'property' => 'formLabel',
'query_builder' => function ($repository) use ($dpt) {
return $repository
->createQueryBuilder('e')
->where('e.departement = :dpt')
->setParameter('dpt', $dpt)
->add('orderBy', 'e.ville ASC')
;
},
));
$builder->add('sexe', 'genemu_jqueryselect2_choice', array(
'empty_value' => '',
'choices' => array(
'homme' => 'Homme',
'femme' => 'Femme',
),
'configs' => array(
'minimumResultsForSearch' => 5,
)
));
$builder->add('date_naissance', 'date', array(
'empty_value' => '',
'widget' => 'choice',
'attr' => array('class' => 'input-small'),
'years' => range(1900,2100),
'months' => range(1,12),
'days' => range(1,31),
));
$builder->add('petit_mot');
$subscriber = new IsAdminFieldSubscriber($builder->getFormFactory());
$builder->addEventSubscriber($subscriber);
}
public function getName()
{
return 'auth_user_registration';
}
}
my EventListener:
<?php
//src/Auth/UserBundle/Form/EventListener/isAdminFieldSubscriber.php
namespace Auth\UserBundle\Form\EventListener;
use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;
class IsAdminFieldSubscriber implements EventSubscriberInterface
{
/**
* #var FormFactoryInterface
*/
private $factory;
/**
* #param FormFactoryInterface $factory
*/
public function __construct(FormFactoryInterface $factory)
{
$this->factory = $factory;
}
/**
* #return array
*/
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_BIND => 'preBind',
);
}
/**
* Called before form data is set
*
* #param DataEvent $event
*/
public function preBind(DataEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
$dpt = $data['localisation'];
$form->add($this->factory->createNamed('localisation', 'entity', null, array(
'empty_value' => '',
'class' => 'AuthGeoBundle:Localisation',
'property' => 'formLabel',
'query_builder' => function ($repository) use ($dpt) {
return $repository
->createQueryBuilder('e')
->where('e.id = :dpt_id')
->setParameter('dpt_id', $dpt)
->add('orderBy', 'e.ville ASC')
;
},
)));
}
}
You explain the problem yourself:
"It's because the submitted value isn't included in the "array" returned by the query builder."
You can use data transformers to solve this issue.