I have a problem with my Symfony5 app.
After submit form the page refresh and nothing happens. What wrong is in the code below? I tried to debug it and check where Controller have some error but i can't find it. In the profiler i can't see query with INSERT, only SELECT.
TopicController:
/**
* #param Request $request
* #Route("/custom", name="custom")
*/
public function custom(Request $request)
{
$form = $this->createFormBuilder()
->add('title', TextType::class, [
'label' => 'Tytuł tematu'
])
->add('description', TextareaType::class, [
'label' => 'Opis tematu',
'attr' => [
'rows' => 5,
'placeholder' => 'Opis tematu...'
]
])
->add('submit', SubmitType::class, [
'attr' => [
'class' => 'btn btn-success btn-block'
],
'label' => 'Zarezerwuj'
])
->add('category', ChoiceType::class, [
'choices' => [
'PWA' => 'PWA',
'RWA' => 'RWA',
'SPA' => 'SPA',
'RIA' => 'RIA',
'REST' => 'REST',
'PHP REST' => 'PHP REST',
'Inna' => 'Inna'
],
'label' => 'Kategoria'
])
->add('techDescription', TextType::class, [
'label' => 'Opis technologii',
'attr' => [
'placeholder' => 'Opis technologii...'
],
'required' => FALSE
])
->getForm();
$form->handleRequest($request);
$form->getErrors();
$topic = new Topic();
$reservation = new Reservation();
if ($form->isSubmitted()) {
if ($form->isValid()) {
$data = $form->getData();
$em = $this->getDoctrine()->getManager();
$topic->setCreatedAt(new \DateTime());
$topic->setUpdatedAt(new \DateTime());
$topic->setCustom(TRUE);
$topic->setTitle($data['title']);
$topic->setTopicDescription($data['topicDescription']);
$em->persist($topic);
$em->flush();
$reservation->setUpdatedAt(new \DateTime());
$reservation->setCreatedAt(new \DateTime());
$reservation->setUser($this->getUser());
$reservation->setCategory($data['category']);
if (!empty($data['techDescription']))
$reservation->setTechDescription($data['techDescription']);
$reservation->setTopic($topic);
$em->persist($reservation);
$em->flush();
if ($reservation->getId() == NULL) {
$em->remove($topic);
$em->flush();
$this->addFlash('error', 'Posiadasz już aktywną rezerwację');
return $this->redirectToRoute('topic.custom');
}
return $this->redirectToRoute('home');
} else {
$this->addFlash('error','Issue with validation');
}
}
return $this->render('topic/custom.html.twig', [
'form' => $form->createView()
]);
custom.html.twig:
{% extends('base.html.twig') %}
{% block content %}
<div class="container mt-4 mb-4 pl-4 pr-4">
<form class="col-md-6 mx-auto" method="" action="">
<input type="hidden" name="token" value="{{ csrf_token('custom') }}"/>
<div class="form-group">
{{ form_row(form.title) }}
</div>
<div class="form-group">
{{ form_row(form.description) }}
</div>
<div class="form-group">
{{ form_row(form.category) }}
<div class="mt-3" id="techDesc" style="display:none">
{{ form_row(form.techDescription) }}
</div>
</div>
{{ form_row(form.submit) }}
</form>
</div>
{% endblock %}
Your code is missing {{ form_start(form) }} and {{ form_end(form) }}
{{ form_start(form) }}
//form
{{ form_end(form) }}
Related
I would like to show error messages in the top of my registration form. I created my registration form:
<div class="example-wrapper">
<h1>Register</h1>
{{ form_start(form) }}
{{ form_row(form.email) }}
{{ form_row(form.plainPassword.first) }}
{{ form_row(form.plainPassword.second) }}
{{ form_row(form.firstname) }}
{{ form_row(form.lastname) }}
{{ form_row(form.termsAccepted) }}
<button type="submit">Register!</button>
{{ form_end(form) }}
</div>
And on my UserType class, I added all necessaries input:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', EmailType::class)
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password'),
'constraints' => [
new NotBlank([
'message' => 'Enter a valid password.'
]),
new Length([
'min' => 8,
'minMessage' => 'Password must be at least 8 characters.'
])
]
))
->add('firstname', TextType::class)
->add('lastname', TextType::class)
->add('termsAccepted', CheckboxType::class, array(
'mapped' => false,
'constraints' => new IsTrue(),
))
;
}}
Every time I get an error message, correctly displayed, I found it under the concerned input and not in the top of my registration form.
I added this on my form but don't help:
{{ form_errors(form) }}
Any suggestion?
Did you set error_bubbling => true?
Documentation: https://symfony.com/doc/current/reference/forms/types/text.html#error-bubbling
I have a form in which I want to have checkboxes to add or remove elements from a collection: a User which have Responsability[].
I want to show some of the existing Responsability in the form but not all of them. I use an attribute called automatic to determine if I want to display them or not.
How can I edit my form to do such a thing?
UserType.php:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username', TextType::class, [
'label' => 'Nom d\'utilisateurice'
])
->add('responsibilities', EntityType::class, [
// looks for choices from this entity
'class' => Responsibility::class,
// uses the Responsibility.label property as the visible option string
'choice_label' => 'label',
'label' => 'Rôles',
'multiple' => true,
'expanded' => true,
'choice_attr' => function($responsibility)
{
return [
'data-responsibility-description' => $responsibility->getDescription(),
];
},
])
->add('submit',SubmitType::class, [
'label' => 'Changer les informations',
'attr' => [
'class' => 'btn btn-outline-primary float-right'
]
]);
}
edit.html.twig:
{{ form_start(edit_form, {'attr': {'id': 'form-edit-user'}}) }}
<div class="form-group">
{{ form_label(edit_form.username) }}
{{ form_widget(edit_form.username) }}
</div>
<div class="form-group">
{{ form_label(edit_form.responsibilities) }}
{% for responsibility in edit_form.responsibilities %}
<div class="form-group">
{{ form_widget(responsibility) }}
{{ form_label(responsibility) }}
<span class="text-muted responsibility-description">
{{ responsibility.vars.attr['data-responsibility-description'] }}
</span>
</div>
{% endfor %}
</div>
{{ form_widget(edit_form) }}
{{ form_end(edit_form) }}
You can use query_builder form option as documented here.
Something like this should work:
'query_builder' => function (EntityRepository $repository) {
return $repository
->createQueryBuilder('o')
->where('o.automatic = FALSE');
}
Or like this if you prefer having a parameter:
'query_builder' => function (EntityRepository $repository) {
return $repository
->createQueryBuilder('o')
->where('o.automatic = :automatic')
->setParameter('automatic', false);
}
list.html.twig:
<div class="load" data-id="1">load User 1</div>
<div class="load" data-id="2">load User 2</div>
<div class="load" data-id="3">load User 3</div>
<div class="result">
{{ form_start(form) }}
<div>
{{ form_label(form.username) }}
{{ form_widget(form.username) }}
{{ form_errors(form.username) }}
{{ form_help(form.username) }}
</div>
<div>
{{ form_label(form.email) }}
{{ form_widget(form.email) }}
{{ form_errors(form.email) }}
{{ form_help(form.email) }}
</div>
<div>
{{ form_widget(form.is_active) }}
{{ form_errors(form.is_active) }}
{{ form_help(form.is_active) }}
</div>
<div>
{{ form_label(form.plainPassword.first) }}
{{ form_widget(form.plainPassword.first) }}
<div class="text-red">{{ form_errors(form.plainPassword.first) }}</div>
{{ form_help(form.plainPassword.first) }}
</div>
<div>
{{ form_label(form.plainPassword.second) }}
{{ form_widget(form.plainPassword.second) }}
<div class="text-red">{{ form_errors(form.plainPassword.second) }}</div>
{{ form_help(form.plainPassword.second) }}
</div>
{{ form_end(form) }}
</div>
<script>
$( ".load" ).on( "click", function() {
var id = $(this).attr("data-id");
$.ajax({
url:'{{ path('pages', { 'slug': page.slug }) }}',
type: "POST",
dataType: "json",
data: {
"id": id
},
async: true,
success: function (data)
{
console.log(data)
$('.result').html(data.output);
}
});
});
</script>
PagesController.php:
if($request->request->get('id')){
$id = $request->request->get('id');
$item = new User();
$item= $this->getDoctrine()->getRepository(User::class)->find($id);
$form = $this->createFormBuilder($item)
->add('username', TextType::class, array('attr' => array('class' => 'form-control')))
->add('email', EmailType::class, array('attr' => array('class' => 'form-control')))
->add('is_active', HiddenType::class)
->add('plainPassword', RepeatedType::class, array('type' => PasswordType::class,'invalid_message' => 'The password fields must match.','options' => array('attr' => array('class' => 'password-field')),'required' => true,'first_options' => array('label' => 'Passwort', 'attr' => array('class' => 'form-control')),'second_options' => array('label' => 'Passwort wiederholen', 'attr' => array('class' => 'form-control')),))
->add('cancel', ButtonType::class, array('label' => 'Abbrechen','attr' => array('class' => 'cancel form-btn btn btn-default pull-right close_sidebar close_h')))
->add('save', SubmitType::class, array(
'label' => 'Update',
'attr' => array('class' => 'btn btn-primary mt-3')
))
->getForm();
$form->handleRequest($request);
$response = new JsonResponse(
array(
'message' => 'Error',
'form' => $this->renderView('list.html.twig',
array(
'entity' => $item,
'form' => $form->createView(),
))), 400);
return $response;
if($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->flush();
return $this->redirectToRoute('pages', array(
'slug' => $slug,
));
}
return $this->render('list.html.twig', [ 'form' => $form->createView()]);
}
By click on a load button I want to load the data from the database into the form. But it is not working, no data is loaded and the error is Ajax request 400
change
$response = new JsonResponse(
array(
'message' => 'Error',
'form' => $this->renderView('list.html.twig',
array(
'entity' => $item,
'form' => $form->createView(),
))), 400);
return $response;
into
$response = new JsonResponse(
array(
'message' => 'Success',
'output' => $this->renderView('list.html.twig',
array(
'entity' => $item,
'form' => $form->createView(),
))), 200);
return $response;
and list.html.twig should ONLY include the form
I try to add a style to the errors messages generated from my RepeatedType in my form by it does no effects.
Here is my code in my controller:
public function signupAction(Request $request)
{
$user = new Users();
$form = $this->createFormBuilder($user)
->add('email', EmailType::class, array(
'required' => true,
'label' => 'e-Mail'
))
->add('password', RepeatedType::class, array(
'type' => PasswordType::class,
'invalid_message' => 'passwords are not identicals',
'options' => array('attr' => array('class' => 'password-field')),
'required' => true,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Confirm password'),
))
->add('submit', SubmitType::class, array(
'label' => 'Submit'
))
->getForm();
And here my code in my twig View:
{% block stylesheets %}
<style>
.error_msg {
color: red;
}
</style>
{% endblock %}
{% block body %}
{{ form_start(form) }}
{{ form_label(form.email) }}
{{ form_widget(form.email) }}
<div class="error_msg">{{ form_errors(form.email) }}</div>
{{ form_label(form.password) }}
{{ form_widget(form.password) }}
<div class="error_msg">{{ form_errors(form.password) }}</div>
{% endblock %}
So, it works well for form.email but not for form.password.
If I try to apply the style on {{ form_errors(form.password.children['first']) }}, the error is displayed 2 times (1 with no style, and 1 with the styles.)
How can I do it ?
Doing as follows, error only displays once (code tested):
{{ form_start(form) }}
{{ form_widget(form.plainPassword.children['first']) }}
<div style="background-color: red;">{{ form_errors(form.plainPassword.children['first']) }}</div>
{{ form_widget(form.plainPassword.children['second']) }}
<div style="background-color: red;">{{ form_errors(form.plainPassword.children['second']) }}</div>
{{ form_end(form) }}
I am in need to displaying an error when two passwords fields are mismatching. I am trying to achieve this through setting invalid_message in my repeated password field, But when I try to call the error as {{form_errors(form.password)}} the error does not appear. However if I use {{form_errors(form)}} the the password mismatch error appears. I need to make the error field specific and would greatly value your input on this :)
I tried many online searches but none helped. Following is my implementation,
the twig
{{ form_start(form, {'attr': {'class': 'form-horizontal', 'role': 'form', 'novalidate': 'novalidate'}}) }}
<!--just placed the error here for debug purposes-->
{{ form_errors(form) }}
<div class="form-group {% if form.email.vars.errors|length > 0 %}has-error{% endif %} {% if form.email.vars.required == 'true' %}required{% endif %}">
{{ form_label(form.email) }}
<div class="col-sm-8">
{{ form_widget(form.email) }}
<span class="help-block">{{ form_errors(form.email) }}</span>
</div>
</div>
<div class="form-group {% if form.password.vars.errors|length > 0 %}has-error{% endif %} {% if form.password.vars.required == 'true' %}required{% endif %}">
{{ form_label(form.password.first) }}
<div class="col-sm-8">
{{ form_widget(form.password.first) }}
</div>
</div>
<div class="form-group required">
{{ form_label(form.password.second) }}
<div class="col-sm-8">
{{ form_widget(form.password.second) }}
</div>
</div>
<div class="form-group">
<div class="center-block btn-sign-in">
{{ form_widget(form.submit) }}
</div>
</div>
<span class="form-footer-msg">Already have an account? Sign In</span>
{{ form_end(form) }}
the form
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('email', 'email', array('label'=>'Email',
'attr'=>array('class'=>'form-control'),
'required'=>true,
'trim' => true,
'data'=>'user1#test.com',
'label_attr'=>array('class'=>'col-sm-3 control-label')));
$builder->add( 'password', 'repeated', array( 'type' => 'password',
//here is the password mismatch error message
'invalid_message' => ErrorMessages::PASSWORDS_DONOT_MATCH,
'options' => array('attr' => array('class' => 'password-field form-control')),
'error_bubbling' => true,
'required' => true,
'trim' => true,
'first_options' => array('label' => 'Password',
'error_bubbling' => true,
'label_attr'=>array('class'=>'col-sm-3 control-label')),
'second_options' => array('label' => 'Confirm password',
'error_bubbling' => true,
'label_attr'=>array('class'=>'col-sm-3 control-label'))));
$builder->add('submit', 'submit', array('label'=>'Create Account',
'attr'=>array('class'=>'btn btn-primary')))
->setMethod('POST')
->getForm();
}
public function getName() {
return 'signup';
}
the controller
public function indexAction() {
$signUp = new User();
$form = $this->createForm(new SignUpForm(), $signUp,
array('action'=>$this->generateUrl('accounts_signup')));
$request = $this->get('request');
$form->handleRequest($request);
if ($request->getMethod() == 'POST') {
if ($form->isValid()) {
$request = $this->get("request");
//do something
}else{
//do something else
}
}
return $this->render('AccountsBundle:Signup:index.html.twig',
array('form'=>$form->createView()));
}
Your input on this matter is greatly appreciated sirs :) thank you very much :)
The error bubbling is not needed. Here is a working example:
$builder->add('password', 'repeated', array(
'type' => 'password',
'label' => 'Zayso Password',
'required' => true,
'attr' => array('size' => 20),
'invalid_message' => 'The password fields must match.',
'constraints' => new NotBlankConstraint($constraintOptions),
'first_options' => array('label' => 'Zayso Password'),
'second_options' => array('label' => 'Zayso Password(confirm)'),
'first_name' => 'pass1',
'second_name' => 'pass2',
));
# twig
{{ form_row(form.password.pass1) }}
{{ form_row(form.password.pass2) }}