I'm trying to make a form with Symfony to be able to adding new row by clicking button. I can't use SubmitType class because after submit symfony can't add new row. ButtonType class doesn't have a basic function isClicked(). Here is my Form:
<?php
namespace App\Form;
use App\Entity\Team;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ButtonType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
final class TeamFormType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('teamName', TextType::class, [
'label' => false,
'attr' => array(
'placeholder' => 'Wpisz Nazwe Drużyny'
)
])
->add('teamCity', TextType::class, [
'label' => false,
'attr' => array(
'placeholder' => 'Wpisz Nazwe Miasta'
)
])
->add('teamCoach', TextType::class, [
'label' => false,
'attr' => array(
'placeholder' => 'Wpisz Imie i Nazwisko Trenera'
)
]);
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
$form = $event->getForm();
for ($i = 1; $i <= 6; $i++) {
$name = 'zawodnik' . $i .'';
$form->add($name, TextType::class, [
'mapped' => false,
'label' => false,
'attr' => array(
'placeholder' => 'Imie i Nazwisko Zawodnika'
)
]);
}
$form->add('agreeTerms', CheckBoxType::class, [
'mapped' => false,
'required' => true,
'label' => 'Zaakceptuj regulamin'
])
->add('Submit', SubmitType::class, [
'label' => 'Wyślij Zgłoszenie'
])
->add('addRow', ButtonType::class, [
'label' => 'Dodaj zawodnika'
]);
});
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Team::class,
'csrf_protection' => true,
'csrf_field_name'=> '_token',
'csrf_token_id' => 'team_item'
]);
}
}
And Controller :
<?php
namespace App\Controller;
use App\Form\TeamFormType;
use Doctrine\DBAL\Types\TextType;
use Doctrine\ORM\EntityManagerInterface;
use http\Env\Request;
use http\Env\Response;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class FormsController extends AbstractController
{
public function createTeamForm(Request $request, EntityManagerInterface $entityManager) :Response
{
$teamEntity = new Team();
$form = $this->createForm(TeamFormType::class);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
if($form->get('addRow')->isClicked()) {
$form->add('something', TextType::class, [
'label' => false,
'attr' => array(
'placeholder' => 'Imie i Nazwisko zawodnika.'
)
]);
}
$entityManager->persist($teamEntity);
$entityManager->flush();
$this->addFlash('success', 'Pomyślnie Utworzono Drużyne');
return $this->redirectToRoute('index');
}
}
}
Anyone have a idea to create button like that ?
I suggest you using Javascript and css, create your row and just hide it, then, onClick, let em appear with a JS function that modify the css sheet
Related
I've Symfony 4.4 and the Symfony/translation component.
I'm trying to extract the translations, and everything works fine, except that the form labels are not extracted.
This is a example of one of the Form Types.
namespace App\Form;
use App\Entity\ClassifiedAd;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ClassifiedAdType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('description')
->add('price', MoneyType::class, [
'required' => false,
'currency' => "EUR"
])
->add('type', ChoiceType::class, [
'required' => true,
'expanded' => true,
'multiple' => false,
'label' => "classifiedad.form.type",
'choices' => [
'classifiedad.form.type_'.ClassifiedAd::SELLING => ClassifiedAd::SELLING,
'classifiedad.form.type_'.ClassifiedAd::SEARCHING => ClassifiedAd::SEARCHING,
'classifiedad.form.type_'.ClassifiedAd::SWAPPING => ClassifiedAd::SWAPPING,
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => ClassifiedAd::class,
]);
}
}
I am experiencing the following form error in Symfony:
Neither the property "email" nor one of the methods "email()", "getemail()"/"isemail()"/"hasemail()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView".
This is what my form looks like:
My App\Form\LostPasswordType:
namespace App\Form;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use App\Entity\LostPassword;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\AbstractType;
class LostPasswordType extends AbstractType
{
public function builder(FormBuilderInterface $builder, array $options)
{
$builder
->setAction('/forgotpw')
->setMethod('POST')
->add('mail', EmailType::class, [
'required' => true,
'label' => false,
'attr' => [
'autofocus' => false,
'class' => 'span8',
'placeholder' => 'example#example.com'
]
])
->add('submit', SubmitType::class, [
'label' => 'Reset Password',
'attr' => ['class' => 'btn btn-primary btn-green']
])
;
}
public function configureOption(OptionsResolver $resolver)
{
$resolver->setDefaults(['data_class' => LostPassword::class]);
}
}
And this is my controller code:
$formReset = $this->createForm(
LostPasswordType::class,
$forgotpass,
array('csrf_protection' => false)
);
$formReset->handleRequest($request);
Does anyone know why I am receiving this error?
I fixed the problem by changing the method function name in form builder, it was mistake there.
I would like to use my UserType form class to register a user and to edit the user profile. As I want to the admins to register a user while setting up their roles, I don't want the user to modify that options. So I would like to use 2 different forms but for the same type User.
Can I create 2 different buildForm() functions in one FormType class ?
Or do I need to create another type ?
Here is my UserType class (main purpose was to register a user) :
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname', TextType::class)
->add('lastname', TextType::class)
->add('birthdate', BirthdayType::class, array(
'placeholder' => '-'))
->add('email', EmailType::class)
->add('username', TextType::class)
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options' => array('label' => 'password'),
'second_options' => array('label' => 'repeat-password'),
))
->add('roles', ChoiceType::class, [
'multiple' => true,
'expanded' => true, // render check-boxes
'choices' => [
'Administrateur' => 'ROLE_ADMIN',
'Direction' => 'ROLE_MANAGER',
'Comptabilite' => 'ROLE_ACCOUNTING',
'Commercial' => 'ROLE_MARKETING',
'Docteur' => 'ROLE_DOCTOR',
'Client' => 'ROLE_CLIENT',
],
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::class,
));
}
}
You can use a variable to dynamically add the roles to the formType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->is_admin = $options['is_admin'];
// [...]
if ($this->is_admin)
$builder
->add('roles', ChoiceType::class, [
'multiple' => true,
'expanded' => true,
'choices' => [
'Administrateur' => 'ROLE_ADMIN',
'Direction' => 'ROLE_MANAGER',
'Comptabilite' => 'ROLE_ACCOUNTING',
'Commercial' => 'ROLE_MARKETING',
'Docteur' => 'ROLE_DOCTOR',
'Client' => 'ROLE_CLIENT',
],
])
// [...]
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
// [...]
'is_admin' => false,
]);
}
Then pass the variable like
$form = $this->createForm(UserType::class, $user, array(
'is_admin' => $this->isGranted('ROLE_ADMIN'),
);
you can easily handle this using array $optionsin controller set choices of roles and add them to $optionand in userType do something like this:
->add('roles', ChoiceType::class, [
'multiple' => true,
'expanded' => true, // render check-boxes
'choices' => $options['choices'],
])
I need language on change of A2LiX Translation tabs. If I click on "FR" then need to get Fr and on click of "NL" need Nl language in form builder ('Need Language Here').
For querybuilder in one field.
Is it possible to get the language in form type when tab change ?
My Form class MixCampaignTranslationType :
<?php
namespace BackEndBundle\Form;
use BackEndBundle\Validator\Constraints\CampaignSlugDuplicate;
use BackEndBundle\Validator\Constraints\MaxMixCampaign;
use Doctrine\ORM\EntityRepository;
use SurveyBundle\Entity\Survey;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Type;
class MixCampaignTranslationType extends AbstractType
{
public $campaignId = null;
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (null !== $options['campaignId']) {
$this->campaignId = $options['campaignId'];
}
$builder
->add('surveys', EntityType::class, [
'class' => Survey::class,
'required' => false,
'multiple' => true,
'mapped' => true,
'attr' => [
'class' => 'select2',
],
'constraints' => new MaxMixCampaign(),
])
->add('startDate', DateTimeType::class, [
'widget' => 'single_text',
'format' => 'yyyy-MM-dd',
'constraints' => new NotBlank(),
'attr' => [
'class' => 'datepicker',
],
])
->add('endDate', DateTimeType::class, [
'widget' => 'single_text',
'format' => 'yyyy-MM-dd',
'constraints' => new NotBlank(),
'attr' => [
'class' => 'datepicker',
],
])
->add('slug', TextType::class, [
'constraints' => [new NotBlank(), new Type('string'), new CampaignSlugDuplicate($this->campaignId, $options['locale'], 'mix')],
])
->add('isClosed');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'SurveyBundle\Entity\MixCampaignTranslation',
'locale' => 'fr',
'campaignId' => null
]);
}
public function getName()
{
return 'back_end_bundle_mix_campaign_translation_type';
}
}
You can create your custom TranslationFormType and then pass the language of loop as current language, Please check as below.
/**
* #param \Symfony\Component\Form\FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventSubscriber($this->translationsListener);
$formsOptions = $this->translationForm->getFormsOptions($options);
foreach ($options['locales'] as $locale) {
if (isset($formsOptions[$locale])) {
$builder->add($locale, $options['form_type'], [
'currentLanguage' => $locale,
'campaignId' => $formsOptions[$locale]['campaignId']
]
);
}
}
}
and you can use currentLanguage to filter data in query_builder in your form_type.
Hope it will help you.
I have an embedded form (oneTo Many relationship).
1 - Entity request
2 - Entity products of the request
I am looking for adapt the form.
I want form can dynamic modify the value when i check the value of the price of this object.
The best is to check the value in the form and compare but I don't know which method can works for my issue.
I would like to do this check in the form "ProductRequestType".
Exemple of my form ProductRequestType :
<?php
namespace \testBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\EntityManager;
class testRequestProductType extends AbstractType {
/** #var \Doctrine\ORM\EntityManager */
private $em;
/**
* Constructor
*
* #param Doctrine $doctrine
*/
public function __construct($em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$disabled_exchange = $options['attr']['disabled_exchange'];
$customer_id = $options['attr']['customer_id'];
$builder->add('id', 'hidden');
$builder->add('part_number');
$builder->add('_number');
$builder->add('source_quantity');
$builder->add('quantity');
$builder->add('serial');
$builder->add('buy_date', 'date', array('required' => false,'widget' => 'single_text', 'fotestt' =>'dd/MM/yy'));
$builder->add('return_date', 'date', array('required' => false,'widget' => 'single_text', 'fotestt' =>'dd/MM/yy'));
$builder->add('is_new', null, array('required' => false));
$builder->add('test_comment');
$builder->add('available_stock', 'integer', array('mapped' => false));
$builder->add('buying_price', 'integer', array('mapped' => false));
$builder->add('test_reason', 'entity',
array(
'class' => 'testBundle:testReason',
'property' => 'name',
'expanded' => false,
'multiple' => false
)
);
//I would like to get the price and if the price < 100 the variable $disabled_exchange = true
if($disabled_exchange){
$builder->add('test_action', 'entity',
array(
'class' => 'testBundle:testAction',
'property' => 'label',
'expanded' => false,
'multiple' => false,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.name != :action')
->setParameter('action', 'exchange');
}
)
);
}else{
$builder->add('test_action', 'entity',
array(
'class' => 'testBundle:testAction',
'property' => 'label',
'expanded' => false,
'multiple' => false
)
);
}
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => '\testBundle\Entity\testRequestProduct',
'disabled_exchange' => false
));
}
public function getName()
{
return 'test_request_product';
}
}
Thank you for your advices.
You can do this by using form event listeners
symfony event doc