J'ai étendu la fonction EntityType
comme UserChooserType
à utiliser avec mon User
et Select2. La liste de choix pour l'entité UserChooserType
provient d'une requête ldap (via un appel ajax), pas d'une requête Doctrine. Le champ est donc vide au départ.
L'entité User est liée à de nombreuses entités différentes dans mon application. Mais si je veux que le type UserChooserType se charge avec un courant l'utilisateur sélectionné, je dois ajouter un listener à chaque formulaire qui l'utilise, par exemple :
class SiteType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$siteAdminOpts = array('label' => 'entity.site.admin', 'required'=>false);
//opts for the UserChooserType
$builder
->add('siteName', FT\TextType::class, array('label' => 'entity.site.name'))
->add('siteAdmin', UserChooserType::class, $siteAdminOpts )
//must be added to every form type that uses UserChooserType with mod for the datatype that $event->getData() returns
->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
$site = $event->getData();
$form = $event->getForm(); //SiteType
if($user = $site->getSiteAdmin()) $siteAdminOpts['choices'] = array($user);
$form->add('siteAdmin', UserChooserType::class, $siteAdminOpts);
});
}
//etc.
tldr ;
J'aimerais que ce soit l'un ou l'autre :
- fixer
UserChooserType
'schoices
à l'utilisateur sélectionné dansUserChooserType::configureOptions()
ou - déplacer
->addEventListener(...)
enUserChooserType::buildForm()
.
Une idée sur la manière de procéder ?
Voici le type de choix de l'utilisateur (UserChooserType) :
class UserChooserType extends AbstractType
{
/**
* @var UserManager
*/
protected $um;
/**
* UserChooserType constructor.
* @param UserManager $um
*/
public function __construct(UserManager $um){
$this->um = $um; //used to find and decorate User entities. It is not a Doctrine entity manager, but it uses one.
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
if (!$data) return;
$user = $this->um->getUserByUserName($data);
if(!$user->getId()) $this->um->saveUser($user); //create User in db, if it's not there yet.
});
$builder->resetViewTransformers(); //so new choices aren't discarded
$builder->addModelTransformer(new CallbackTransformer(
function ($user) { //internal storage format to display format
return ($user instanceof User) ? $user->getUserName() : '';
},
function ($username) { //display format to storage format
return ($username) ? $this->um->getUserByUserName($username) : null;
}
));
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'class' => 'ACRDUserBundle:User',
'label' => 'ldap.user.name',
'choice_label' => function($user, $key, $index){
$this->um->decorateUser($user);
$label = $user->getDetail('displayName');
return $label ? $label : $user->getUserName();
},
'choice_value' => 'userName',
'choices' => [],
'attr' => array(
'class' => 'userchooser',
'placeholder' => 'form.placeholder.userchooser'
)
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'my_userchooser';
}
/**
* @inheritDoc
*/
public function getParent() {
return EntityType::class;
}
}