How can I change error message in Symfony - symfony

I create a form and then when I click on submit button, show this error message:
Please select an item in the list.
How can I change this message and style it ( with CSS )?
Entity:
...
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank(message="Hi user, Please select an item")
*/
private $name;
...
Controller:
...
public function index(Request $request)
{
$form = $this->createForm(MagListType::class);
$form->handleRequest($request);
return $this->render('index.html.twig', [
'form' => $form->createView()
]);
}
...
Form:
...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', EntityType::class,[
'class' => InsCompareList::class,
'label' => false,
'query_builder' => function(EntityRepository $rp){
return $rp->createQueryBuilder('u')
->orderBy('u.id', 'ASC');
},
'choice_label' => 'name',
'choice_value' => 'id',
'required' => true,
])
->add('submit', SubmitType::class, [
'label' => 'OK'
])
;
...
}

In order to use custom messages, you have to put 'novalidate' on your HTML form. For example:
With Twig:
{{ form_start(form, {attr: {novalidate: 'novalidate'}}) }}
{{ form_widget(form) }}
{{ form_end(form) }}
Or in your controller:
$form = $this->createForm(MagListType::class, $task, array( //where task is your entity instance
'attr' => array(
'novalidate' => 'novalidate'
)
));
This Stackoverflow answer has more info on how to use novalidate with Symfony. You can also check the docs for more info.
As for the styling, you can use JavaScript to trigger classes, which you can then style in your CSS, like in this example taken from Happier HTML5 Form Validation . You can also take a look at the documentation on MDN and play with the :valid and :invalid selectors.
const inputs = document.querySelectorAll("input, select, textarea");
inputs.forEach(input => {
input.addEventListener(
"invalid",
event => {
input.classList.add("error");
},
false
);
});
EDIT:
You are probably not seeing your custom message because it comes from server side, the message that you're currently seeing when submitting your form is client-side validation. So you can either place novalidate on your field, or you can override the validation messages on the client side by using setCustomValidity(), as described in this SO post which also contains many useful links. An example using your Form Builder:
$builder
->add('name', EntityType::class,[
'class' => InsCompareList::class,
'label' => false,
[
'attr' => [
'oninvalid' => "setCustomValidity('Hi user, Please select an item')"
]
],
'query_builder' => function(EntityRepository $rp){
return $rp->createQueryBuilder('u')
->orderBy('u.id', 'ASC');
},
'choice_label' => 'name',
'choice_value' => 'id',
'required' => true,
])
->add('submit', SubmitType::class, [
'label' => 'OK'
]);

Related

Rendering a template with form inside from a service

my DataTable service code is given below
public function dataTableTest(string $class, Request $request, $FormBuilder): Response
{
$FormFactory = Forms::createFormFactory();
$form = $FormFactory
//->createBuilder()
->create('App\Form\NewsType', null, array(
'method' => 'POST',
))
->add('task', TextType::class, [
'label' => 'Some task',
'required' => true,
])
->add('dueDate', DateType::class)
->add('save', SubmitType::class, [
'label' => 'Create',
])
//->getForm()
;
$response = $this->twig->render('forms/FormFactory.html.twig', [
'controller_name' => 'FormsController',
'form' => $form->createView(),
]);
return new Response($response);
}
FormFactory.html.twig code is
{{ form(form) }}
and i have an error
SyntaxError HTTP 500 Internal Server Error
Unknown "form" function.
1 so how can render a template with twig function 'form' ? or its not possible?
2 When i render some template from service than
a)twig knows entity functions or properties like 'array.id'
b)twig does not know all twig functions like form(), form_start
and so on.
c) I think i need some extra twig dependency injections

How to to an orderby on a ManyToMany relation field

i got an entity called "Recipes" that has a relation with another entity called "Ingredients".
/**
* #ORM\ManyToMany(targetEntity=Ingredients::class, inversedBy="recettes")
*/
private $ingredient;
What i need is to list all ingredients via my form builder, and it works well :
->add('ingredient', EntityType::class, [
// looks for choices from this entity
'class' => Ingredients::class,
'choice_label' => 'nom',
// used to render a select box, check boxes or radios
'multiple' => true,
'expanded' => true,
'label' => 'Ingrédients de la recette'
])
But i need to list them ordered by their name, so i've tried to add this line on my "Recipes ingredient field" :
* #OrderBy({"nom" = "ASC"})
But ingredients remains not ordered by their name.
Am i missing something ? :)
/**
* ...
* #ORM\OrderBy({"nom" = "ASC"})
*/
private $recettes;
or
->add('ingredient', EntityType::class, [
// looks for choices from this entity
'class' => Ingredients::class,
'choice_label' => 'nom',
// used to render a select box, check boxes or radios
'multiple' => true,
'expanded' => true,
'label' => 'Ingrédients de la recette',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')->orderBy('u.nom', 'ASC');
},
])

Symfony Form - Add required fields to form depending on other field value

I want to add some required fields to my form when an other field has some value. I've tried to do it with PRE_SET_DATA event but I cannot get data in my event.
My example here is to add partner name field when a user is married.
My UserType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('familyStatus', ChoiceType::class, [
'label' => 'Statut de famille',
'label_attr' => [
'class' => 'fg-label'
],
'attr' => [
'class' => 'sc-gqjmRU fQXahQ'
],
'required' => true,
'choices' => [
'Married' => 'M',
'Single' => 'S'
]
])
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$user = $event->getData();
$status = $user->getFamilyStatus(); // Give me NULL
//$status = $form->get('familyStatus')->getData() Give me NULL too
/*
if ($user && $status === 'M') {
$form->add('partnerName', TextType::class, [
'required' => true,
'mapped' => false
]);
)
*/
})
;
}
What's wrong ? How can I add dynamically new fields depending on other field ?
I also tried with POST_SET_DATA but it's not working.
You need the second example from this part of the docs link.
Basically you set the event listener to the entire form. You should add another listener to the field itself with POST_SUBMIT event.

Displaying returned array as radio buttons

I'm trying to display a set of radio buttons (male or female) on my index page. Within my Form I build the form like this:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('gender', ChoiceType::class, array(
'choices' => array(
'Male' => 1,
'Female' => 2,
)));
}
Then within the Controller:
public function indexAction(Request $request)
{
$participantEntry = new Participants();
$form = $this->createForm(ParticipantsType::class, $participantEntry,[
'action' => $request->getUri()
]);
$form->handleRequest($request);
return $this->render('SurveyBundle:Page:index.html.twig',
['form' => $form->createView()]);
}
However, I'm not sure how to actually display as RadioButtons within my Twig file, this is what I've tried:
{% for g in form.gender %}
{{ g.value }}
{% endfor %}
BTW: The $gender within my Entity is an int
Which doesn't work, does anyone know what I am doing wrong?
Change the add into builder as follow
->add('gender', ChoiceType::class, array(
'choices' => array(
'Male' => 1,
'Female' => 2,
),
'expanded' => true,
'multiple' => false
);
The combination of 'expanded' => true and 'multiple' => false will generate radio buttons, then in twig, just use
form_widget(form.gender)

How to get rid of the Invalide CSRF token error

I have a symfony form. Submitting it, I have an error message :
The CSRF token is invalid. Please try to resubmit the form.
I dont know why I have this. I bind request to form after checking the request method is post :
if ($request->getMethod() === 'POST') {
$form->handleRequest($request);
}
Here is the type of the form.
class PasswordActionType extends AbstractType {
protected $forgotten_password;
public function __construct($forgotten_password) {
$this->forgotten_password = $forgotten_password;
}
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder, array $options) {
$builder->add('identifiant', 'text', array('attr' => array('style' => 'width:250px')));
if(!$this->forgotten_password) {
$builder->add('ancienMDP', 'password', array(
'label' => 'Ancien MDP',
'attr' => array(
'class' => 'ligne',
'style' => 'width:252px'
)));
$builder->add('nouveauMDP', 'repeated', array(
'type' => 'password',
'invalid_message' => 'Confirmation différente du nouveau mot de passe',
'first_options' => array('label' => 'Nouveau MDP'),
'second_options' => array('label' => 'Confirmer'),
'options' => array(
'attr' => array(
'class' => 'ligne',
'style' => 'width:252px'
))
));
} else {
$builder->add('ancienMDP', 'hidden', array('error_bubbling' => false, 'data' => 'NULL'));
$builder->add('nouveauMDP', 'hidden', array('error_bubbling' => false, 'data' => 'NULL'));
}
}
public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'My\Bundle\Security\PasswordAction',
'csrf_protection' => true,
'csrf_field_name' => 'token'
));
}
public function getName() {
return 'cramif_password_action';
}
}
So 2 forms use the same builder. The difference is the value of "forgotten_password".
form1 : forgotten_password = true
the 2 fields 'ancienMDP' and 'NouveauMDP' are hidden html fields
form2: forgotten_password = false
the 2 fields are what u can see.
There is not problem with form1, no CSRF error.
The problem occurs with form2.
Note : the 2 forms are displayed with Twig with the same commands.
Note2 : in the twig template I have a form_rest
Just to help people :
If u think u did it right :
bind the request after checking that the form is posted
used form_rest.
Check that you did not invalidate your session. Of course, for the CSRF to work, you need a valid session.

Resources