-
-
Save doxt3r/b28a56ebcfda21ddb3f5bc6ecb1ddf58 to your computer and use it in GitHub Desktop.
Symfony TagType
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Form\EventListener; | |
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
use Doctrine\ORM\EntityManager; | |
use Symfony\Component\Form\FormEvents; | |
use Symfony\Component\Form\FormEvent; | |
class AddEntityChoiceSubscriber implements EventSubscriberInterface | |
{ | |
/** | |
* @var EntityManager | |
*/ | |
protected $em; | |
/** | |
* The name of the entity | |
* | |
* @var string | |
*/ | |
protected $entityName; | |
public function __construct(EntityManager $em, string $entityName) | |
{ | |
$this->em = $em; | |
$this->entityName = $entityName; | |
} | |
public static function getSubscribedEvents() | |
{ | |
return [ | |
FormEvents::PRE_SUBMIT => 'preSubmit', | |
]; | |
} | |
public function preSubmit(FormEvent $event) | |
{ | |
$data = $event->getData(); | |
if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { | |
$data = []; | |
} | |
// loop through all values | |
$repository = $this->em->getRepository($this->entityName); | |
$choices = array_map('strval', $repository->findAll()); | |
$className = $repository->getClassName(); | |
$newChoices = []; | |
foreach($data as $key => $choice) { | |
// if it's numeric we consider it the primary key of an existing choice | |
if(is_numeric($choice) || in_array($choice, $choices)) { | |
continue; | |
} | |
$entity = new $className($choice); | |
$newChoices[] = $entity; | |
$this->em->persist($entity); | |
} | |
$this->em->flush(); | |
// now we need to replace the text values with their new primary key | |
// otherwise, the newly added choice won't be marked as selected | |
foreach($newChoices as $newChoice) { | |
$key = array_search($newChoice->__toString(), $data); | |
$data[$key] = $newChoice->getId(); | |
} | |
$event->setData($data); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{{ form(form) }} | |
<script> | |
const select = document.querySelector('.js-select2'); | |
$(select).select2({ | |
tags: true, | |
}); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Form\Type; | |
use Symfony\Component\Form\FormBuilderInterface; | |
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |
use Symfony\Component\OptionsResolver\OptionsResolver; | |
class DemoType extends AbstractNoteType | |
{ | |
/** | |
* {@inheritdoc} | |
*/ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder | |
->add('tags', TagType::class, [ | |
'required' => true, | |
'class' => 'AppBundle:Tag', | |
'multiple' => true, | |
'attr' => [ | |
'class' => 'js-select2', | |
], | |
]) | |
; | |
parent::buildForm($builder, $options); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Entity; | |
use Doctrine\ORM\Mapping as ORM; | |
use Symfony\Component\Validator\Constraints as Assert; | |
/** | |
* @ORM\Entity | |
* @ORM\Table | |
*/ | |
class Tag | |
{ | |
/** | |
* @ORM\Id | |
* @ORM\Column(type="integer") | |
* @ORM\GeneratedValue(strategy="AUTO") | |
*/ | |
protected $id; | |
/** | |
* @ORM\Column(type="string", length=50, nullable=false, unique=true) | |
* @Assert\NotBlank() | |
*/ | |
protected $value = ''; | |
public function __construct(string $value = '') | |
{ | |
$this->value = $value; | |
} | |
/** | |
* @return int|null | |
*/ | |
public function getId() | |
{ | |
return $this->id; | |
} | |
/** | |
* @param string $value | |
*/ | |
public function setValue(string $value) | |
{ | |
$this->value = $value; | |
return $this; | |
} | |
/** | |
* @return string | |
*/ | |
public function getValue(): string | |
{ | |
return $this->value; | |
} | |
/** | |
* @return string | |
*/ | |
public function __toString(): string | |
{ | |
return $this->value; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Form\Type; | |
use Symfony\Component\Form\AbstractType; | |
use Symfony\Component\Form\FormBuilderInterface; | |
use AppBundle\Form\EventListener\AddEntityChoiceSubscriber; | |
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |
class TagType extends AbstractType | |
{ | |
/** | |
* {@inheritdoc} | |
*/ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$subscriber = new AddEntityChoiceSubscriber($options['em'], $options['class']); | |
$builder->addEventSubscriber($subscriber); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getParent() | |
{ | |
return EntityType::class; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getName() | |
{ | |
return 'tag'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment