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,
]);
}
}
Related
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
I am trying to use all the power of Symfony to build a site. I already have 2 years of experience in Symfony but for the first time, I am trying to use the concept of custom form type to create a specific registration form. I already have a registration form for basic users but now, I want to create another one for managers whom operate hotels.
I have already created a form type named RegistrationFormType and another one named HotelType. My thing is that I want to use both of these form types in one form. But I keep getting an exception which says
Neither the property "user" nor one of the methods "getUser()",
"user()", "isUser()", "hasUser()", "__get()" exist and have public
access in class "App\Entity\User"
I have followed whatever was said in the Symfony official documentation about custom form types.
I made this form type RegistrationHotelFormType which is made up of another form RegistrationFormType used elsewhere as a form for basic users to create accounts and HotelType generated by Symfony itself.
<?php
namespace App\Form;
use App\Entity\User;
use App\Form\HotelType;
use App\Form\RegistrationFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\File;
class RegistrationHotelFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user', RegistrationFormType::class, ['mapped' => false])
->add('hotel', HotelType::class, ['mapped' => false])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
This above use to work but in the Symfony documentation, I don't need to set a mapped parameter to false knowing that I want form values to be assigned to objects fields which are Hotel and User. How can I get this done? (https://symfony.com/doc/current/form/create_custom_field_type.html#creating-form-types-created-from-scratch).
RegistrationFormType:
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\File;
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', EmailType::class, ['error_bubbling'=>true, 'label' => 'Email', 'attr' => ['type'=>'text','class'=>'form-control', 'placeholder'=>'Email', 'aria-label'=>"Username", 'aria-describedby'=>"basic-addon1"]])
->add('plainPassword', RepeatedType::class, [
'type' => PasswordType::class,
'label' => 'Mot de passe',
'attr' => ['error_bubbling'=>true,
'type'=>'text',
'class'=>'form-control',
'placeholder'=>'Mot de passe',
'aria-label'=>"Username",
'aria-describedby'=>"basic-addon1"],
'mapped' => false,
'constraints' => [
new NotBlank([
'message' => 'Mot de passe requis',
]),
new Length([
'min' => 8,
'minMessage' => 'Le mot de passe doit avoir au moins {{ limit }} caractères',
// max length allowed by Symfony for security reasons
'max' => 128,
'maxMessage' => 'Le mot de passe ne doit pas dépasser {{ limit }} caractères',
]),
// new Regex([
// 'pattern' => '/^\S*(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])\S*$/',
// 'message' => 'Le mot de passe doit contenir au moins 1 lettre et 1 chiffre',
// ])
],
])
->add('firstname', TextType::class, ['error_bubbling'=>true, 'label' => 'Prénom', 'attr' => ['type'=>'text','class'=>'form-control', 'placeholder'=>'Prénom', 'aria-label'=>"Username", 'aria-describedby'=>"basic-addon1"]])
->add('surname', TextType::class, ['error_bubbling'=>true, 'label' => 'Nom', 'attr' => ['type'=>'text','class'=>'form-control', 'placeholder'=>'Nom', 'aria-label'=>"Username", 'aria-describedby'=>"basic-addon1"]])
->add('phoneNumber', TextType::class, ['error_bubbling'=>true, 'label' => 'Téléphone', 'attr' => ['type'=>'text','class'=>'form-control', 'placeholder'=>'Téléphone', 'aria-label'=>"Username", 'aria-describedby'=>"basic-addon1"]])
->add('city', TextType::class, ['error_bubbling'=>true, 'label' => 'Ville', 'attr' => ['type'=>'text','class'=>'form-control', 'placeholder'=>'Ville', 'aria-label'=>"Username", 'aria-describedby'=>"basic-addon1"]])
->add('termsAccepted', CheckboxType::class, [
'error_bubbling'=>true,
'mapped' => false,
'constraints' => new IsTrue(),
'attr' => ['type'=>"checkbox", 'class'=>"form-check-input"]
])
->add('resumePDF', FileType::class, [
'error_bubbling'=>true,
'label' => 'CV (Fichier PDF)',
'mapped' => false,
'required' => true,
'constraints' => [
new File([
'maxSize' => '1024k',
'mimeTypes' => [
'application/pdf',
'application/x-pdf',
],
'mimeTypesMessage' => 'Téléchargez un fichier PDF valide',
])
],
'attr' => ['type'=>"file", 'class'=>"custom-file-input"]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
HotelType
<?php
namespace App\Form;
use App\Entity\Hotel;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class HotelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('address');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Hotel::class,
]);
}
}
RegistrationController.php
/**
* #Route("/inscription-hotel", name="app_register_hotel")
*/
public function registerHotel(Request $request, UserPasswordEncoderInterface $passwordEncoder, \Swift_Mailer $mailer): Response
{
$session = new Session();
// $session->start();
$user = new User();
$form = $this->createForm(RegistrationHotelFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
}
return $this->render('registration/register-hotel.html.twig', [
'registrationForm' => $form->createView(),
]);
}
Thanks in advance for your help
Cerad diagnosed why the error is triggered (the second argument to createForm will be used and the form will try to access the user and hotel property on it), the simplest solution follows:
I would remove the data_class from the combined form, and just omit the second parameter to createForm in your controller. The return value of $form->getData() would be an array:
['user' => {User object}, 'hotel' => {Hotel object}]
(you can also provide a similarly structured array to your createForm call as the second parameter)
of course, you can create a new class that contains both the user and the hotel...
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