famas23
famas23

Reputation: 2280

Default select option for EntityType Field

I have two classes User.php and Group.php, extended from the classes defined in fosuserbundle .

Besides this I have a ManyToMany relation between them .

The idea of the application is when I add a new user, I assign one or many groups to user (I am using material design multi select option). The problem arises when user does not have any group(s) assigned (e.g when group option is empty). I get this javascript error in the console:

An invalid form control with name='user[groups][]' is not focusable.

So to resolve this issue, I need to provide a default value for group field. How to set a default user group if group is not selected ? My classes are defined as follow.

UserType.php

 public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add(
                'username',
                null,
                array(
                'attr' => array(
                    'placeholder' => 'username'
                ),
            ))
            ->add(
                'email',
                null,
                array(
                'attr' => array(
                    'placeholder' => 'email'
                ),
            ))
            /*->add('groups', EntityType::class, array(
                'class' => 'AppBundle\Entity\Group',
                'choice_label' => 'name',
                'expanded' => false,
                'multiple' => false
            ))  */
            ->add('groups', EntityType::class, array(
                'class' => 'AppBundle\Entity\Group',
                'choice_label' => 'name',
                'attr'=>array(
                    'class' => 'mdb-select'
                ),
                'multiple' => true,
            )) 
            ->add('plainPassword', RepeatedType::class, array(
                'invalid_message' => 'Les mots de passe doivent être identiques.',
                'first_options'  => array('label' => 'Mot de passe'),
                'second_options' => array('label' => 'Répétez le mot de passe'),
            ))
            //<input id="input-id"  type="file" class="file" multiple data-show-upload="false" data-show-caption="true">
            ->add('enabled', null, array(
                'required' => false, 
            ))
            ->add('imageFile',VichFileType::class, [
                'required' => false,   
                'download_link' => true,
                'attr'=>array(
                'type' => 'file',
                'onchange' => 'loadFile(event)'), // not mandatory, default is true
            ])
        ;
    }

GroupEntity.php

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('roles', CollectionType::class, array(
                'entry_type'   => ChoiceType::class,
                'entry_options'  => array(
                    'attr' => array(
                        'class'=>'mdb-select colorful-select dropdown-default'
                    ),
                    'choices'  => array(
                        'Admin' => 'ROLE_ADMIN',
                        'USER'     => 'ROLE_USER',
                    ),
                )
            ))
        ;
    }

User.php

 <?php


    namespace AppBundle\Entity;

    use FOS\UserBundle\Model\User as BaseUser;
    use Doctrine\ORM\Mapping as ORM;
    use Doctrine\Common\Collections\ArrayCollection;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    use Symfony\Component\HttpFoundation\File\File;
    use Vich\UploaderBundle\Mapping\Annotation as Vich;

    /**
     * @Vich\Uploadable
     * @ORM\Entity
     * @ORM\Table(name="fos_user")
     * @UniqueEntity(fields="usernameCanonical", errorPath="username", message="fos_user.username.already_used", groups={"Default", "Registration", "Profile"})
     * @UniqueEntity(fields="emailCanonical", errorPath="email", message="fos_user.email.already_used", groups={"Default", "Registration", "Profile"})
     */
    class User extends BaseUser {

        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         * 
         */
        protected $id;

        /**
         * 
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Group", inversedBy="users", cascade={"remove"})
         * @ORM\JoinTable(name="fos_user_user_group",
         *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
         *      inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
         * )
         */
        protected $groups;

        /**
         * @ORM\Column(type="integer", length=6, options={"default":0})
         */
        protected $loginCount = 0;

        /**
         * @var \DateTime
         *
         * @ORM\Column(type="datetime", nullable=true)
         */
        protected $firstLogin;
        /**
         * NOTE: This is not a mapped field of entity metadata, just a simple property.
         * 
         * @Vich\UploadableField(mapping="user_image", fileNameProperty="imageName")
         * 
         * @var File
         */
        private $imageFile;

        /**
         * @ORM\Column(type="string", length=255,nullable=true)
         *
         * @var string
         */
        private $imageName;

        /**
         * @ORM\Column(type="datetime",nullable=true)
         *
         * @var \DateTime
         */
        private $updatedAt;


        public function __construct() {
            parent::__construct();
            $this->enabled = true;
            $this->groups = new ArrayCollection();
        }
    }

Group.php

namespace AppBundle\Entity;

use FOS\UserBundle\Model\Group as BaseGroup;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="fos_group")
 */
class Group extends BaseGroup
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
     protected $id;

    /** 
      * @ORM\ManyToMany(targetEntity="AppBundle\Entity\User", mappedBy="groups") 
      * 
      *   
      */ 
     protected $users;

    /**
     * @var string
     */
    protected $name;

    /**
     * @var array
     */
    protected $roles;

    /**
     * Group constructor.
     *
     * @param string $name
     * @param array  $roles
     */
    public function __construct($name, $roles = array())
    {
        $this->name = $name;
        $this->roles = $roles;
    }

}

Upvotes: 3

Views: 1111

Answers (2)

Mawcel
Mawcel

Reputation: 1995

You can achieve that by adding a 'POST_SET_DATA' or 'PRE_SUBMIT' form event to assign a group to the user if there aren't any groups in the form data.

$builder->addEventListener(FormEvents::POS_SET_DATA, function (FormEvent $event) {
        $user = $event->getData();
        $form = $event->getForm();


        if (!$user->getGroups->count() > 0) {
            //...
        }
    });

http://symfony.com/doc/current/form/dynamic_form_modification.html https://symfony.com/doc/current/form/events.html

you could also use a lifecycle callback for your user entity

http://symfony.com/doc/current/doctrine/lifecycle_callbacks.html

or directly modify the object in your controller (@martin 's answer)

Upvotes: 1

martin
martin

Reputation: 96959

You need to pass the default data when creating the form. For example in your controller you'll have:

$user = new User();
// Add default groups to the $user
// ...
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);

if ($form->isValid()) {
    $data = $form->getData();
    // ...
}

Upvotes: 2

Related Questions