I have a custom action, based on the editAction from Sonata. Only the form is different.
public function customAction(){
$id = $this->get('request')->get($this->admin->getIdParameter());
$object = $this->admin->getObject($id);
if (!$object) {
throw new NotFoundHttpException(sprintf('unable to find the object with id : %s', $id));
}
if (false === $this->admin->isGranted('EDIT', $object)) {
throw new AccessDeniedException();
}
// On vérifie que l'annonce appartient bien à l'utilisateur connecté
if($this->getUser()->getId() !== $object->getUser()->getId()) {
throw new AccessDeniedException();
}
$em = $this->getDoctrine()->getManager();
$preparechoices = $em->getRepository('AcmeBundle:Entity')->findAll();
foreach($preparechoices as $c){
$choices[$c->getId()] = $c->getLibelle();
}
$form = $this->createFormBuilder(array('choix'=>1))
->add('choix','choice',array('choices'=>$choices))
->add('submit','submit')
->getForm();
$view = $form->createView();
$this->admin->setSubject($object);
$this->get('twig')->getExtension('form')->renderer->setTheme($view, $this->admin->getFormTheme());
return $this->render($this->admin->getTemplate('EDIT'), array(
'action' => 'edit',
'object' => $object,
'form' => $view,
));
}
But I got this error :
Impossible to access a key ("default") on a boolean variable ("")
The error come from this line in the twif file :
{{ form_helper.render_groups(admin, form, admin.formtabs['default'].groups, has_tab) }}
I can't find how to fix it, does anyone know ?
Thanks to Joshua, i was able to fix the error by adding this line:
$this->admin->setFormTabs(array('default'=>array('groups' => array())));
But now, i got a new error :
Impossible to access an attribute ("help") on a null variable
Form form_admin_fields.html.twig, this line, because sonata_admin.field_description is null :
{% if sonata_admin.field_description.help %}
title="{{ sonata_admin.admin.trans(sonata_admin.field_description.help, {}, sonata_admin.field_description.translationDomain)|raw }}"
{% endif %}
I don't know how to fix it, i tried several test, whitout success, in the form definition like :
$form = $this->createFormBuilder(array('choix'=>1))
->add('choix','choice',array('choices'=>$choices,'sonata_admin'=>array('field_description'=>array('help'=>'help_message'))))
->add('submit','submit')
->getForm();
Related
I use Symfony 4.4. I have a go back button in my Twig template.
{% if previousPageboolean == false %}
<a class="d-block text-decoration-none cursor px-4 pt-3" href="{{app.request.headers.get('referer')}}"><img src="{{ asset('build/images/back.svg')}}" class="height-19"></a>
{%else%}
<a class="d-block text-decoration-none cursor px-4 pt-3" href="{{referer}}"><img src="{{ asset('build/images/back.svg')}}" class="height-19"></a>
{% endif %}
But I have a problem. It works but in this template I have 2 forms. When I click the submit button of these buttons, flash messeges apper and reload the page. So when page reload the route of the go back button change and it is the own page.
Controller
/**
* #Route("/receta/{title}", name="recipe_show", methods={"GET"})
* #Route("/receta/{title}", name="recipe_show")
*/
public function show(Recipe $recipe,RecipeRepository $recipeRepository,ScoreRepository $scoreRepository,CommentRepository $commentRepository, Request $request): Response
{
$comment = new Comment();
$score = new Score();
$comment_form = $this->createForm(CommentType::class, $comment);
$comment_form->handleRequest($request);
$score_form = $this->createForm(ScoreType::class, $score);
$score_form->handleRequest($request);
$entityManager = $this->getDoctrine()->getManager();
$user = $this->getUser();
$referrer="";
$previousPageboolean =false;
if ($score_form->isSubmitted() && $score_form->isValid()) {
$previousPageboolean =true;
$referrer = $request->get('referrer');
$score_value = $score_form->get("score")->getData();
$isScore = $scoreRepository->findBy(array('user' => $user , 'recipe' => $recipe->getId()));
if($isScore == [] ){
$score->setScore($score_value);
$score->setRecipe($recipe);
$score->setUser($user);
$entityManager->persist($score);
$entityManager->flush();
$this->addFlash('success', '¡Puntuación registrada con exito!');
return $this->redirectToRoute($request->getUri(), [
'referrer' => $this->generateUrl($request->attributes->get('_route'),
array_merge(
$this->request->atrributes->get('_route_params'),
$this->request->query->all
),
),
]);
}else{
$this->addFlash('danger', 'Ya existe una puntuación registrada para esta receta con este usuario.');
return $this->redirect($request->getUri());
}
}
if ($comment_form->isSubmitted() && $comment_form->isValid()) {
$parentid = $comment_form->get("parent")->getData();
if($parentid != null){
$parent = $entityManager->getRepository(Comment::class)->find($parentid);
}
$comment->setVisible(1);
$comment->setParent($parent ?? null);
$comment->setUser($user);
$comment->setRecipe($recipe);
$comment->setCreatedAt(new DateTime());
$entityManager->persist($comment);
$entityManager->flush();
$this->addFlash('success', '¡Comentario registrado con exito!');
return $this->redirect($request->getUri());
}
$comments = $commentRepository->findCommentsByRecipe($recipe);
return $this->render('recipe/show/show.html.twig', [
'recipe' => $recipe,
'score_form' => $score_form->createView(),
'comment_form' => $comment_form->createView(),
'comments' => $comments,
'referrer' => $referrer,
'previousPageboolean' => $previousPageboolean
]);
}
It isn't a good idea to put the name of the route in the back button because the route needs the category parameter and a recipe can have more than one categories.
The recipe table haven't a category property because I have a recipes_categories table which have a M:M relationship between recipe table and category table.
Don't know if it has something to do with your problem but I think there's a typo in your controller: array_merge(
$this->request->atrributes->get('_route_params'),
One workaround I can think of is passing the refferer as a query parameter, and including it in the twig file.
In case you redirect to the current controller from twig:
Link to the current controller
In case you redirect using RedirectResponse:
return $this->redirectToRoute('some_path', [
...,
'referrer' => $this->generateUrl($request->attributes->get('_route'),
array_merge(
$request->atrributes->get('_route_params'),
$request->query->all
),
),
]);
Controller:
public function show(Request $request, ...)
{
...
$referrer = $request->get('referrer');
...
return $this->render('recipe/show/show.html.twig', [
...,
'referrer' => $referrer,
]);
twig:
<a class="d-block text-decoration-none cursor px-4 pt-3" href="{{referrer}}"><img src="{{ asset('build/images/back.svg')}}" class="height-19"></a>
I am using symfony3 with window 7 AND using custom form rending. like that
{{ form_start(form,{ 'attr': {'class': 'form-horizontal','role':'form','id':'form'} }) }}
---- form field here
{{ form_widget(form._token) }}
{{ form_end(form, {'render_rest': false}) }}
/**
* #Route("entity/entity/{id}", name="entity_entity",defaults={"id" = 0})
*/
public function entityAction(Request $request,$id){
$action = false;
$arr_XYZ_data = array();
$arr_XYZ_prepare_data = array();
$form_title = 'Add New XYZ';
$obj_XYZ = new XYZ();
$form = $this->createForm(XYZType::class, $obj_XYZ);
if($id!=0){
$obj_repo = $this->getDoctrine()->getRepository('AppBundle:XYZ');
$arr_XYZ_data = $obj_repo->find($id);
if($arr_XYZ_data){
$action = true;
$form_title = 'Update XYZ';
$arr_XYZ_data = $obj_repo->findXYZById($id);
$arr_XYZ_prepare_data = $this->_prepareData($arr_XYZ_data);
}
}
$form->handleRequest($request);
if (($form->isSubmitted())&&($form->isValid())) {
$obj_XYZ->setXYZId($id);
$str_hiddenfield_result = $form->get('extraformfield')->getData();
$arr_hiddenfield_result = explode('&',$str_hiddenfield_result);
$obj_XYZ->setDef($obj_XYZ->getDef()->getDefId());
$obj_XYZ->setAbc($arr_hiddenfield_result[3]);
$obj_XYZ->setAuthor(1); //ldap session value
$em = $this->getDoctrine()->getManager();
$em->persist($obj_XYZ);
$em->flush();
$this->addFlash('success', 'Your record has been added successfully!');
return $this->redirectToRoute('XYZ_index', array(), 301);
}else{
$form->getErrors();
}
}
above code does not print any error but unable to submit. so please anyone can suggest me how can i fix the issue.
how to get all error in string with corresponding each form field.
Just calling the getter will not print anything, you need to do it by yourself using another (printing) function.
return new \Symfony\Component\HttpFoundation\Response($form->getErrors());
It will render a string containing all errors.
Depending on the context (traditional, ajax, ...), you can just re-render the form like so:
return $this->render('YourBundle:YourView.html.twig', [
'form' => $form->createView(),
]);
The errors should be properly displayed.
i need to display information of a product from my database but i have an
error: Controller
"UserBundle\Controller\DefaultController::profileAction()" requires
that you provide a value for the "$id" argument (because there is no
default value or because there is a non optional argument after this
one).
This is the profileAction:
public function profileAction($id)
{
$product = $this->getDoctrine()
->getRepository('UserBundle:Product')
->find($id);
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$id
);
}
return $this->render('UserBundle:Default:profile.html.twig', array('product' =>$product));
}
please someone help me.
You need to provide $id as argument.
Change the return to something like that:
return $this->render('UserBundle:Default:profile.html.twig', ['product' => $product, 'id' => $id]);
You need a route like that :
_my_route:
path: /my_path/{id}
defaults: {controller: AcmeBundle:Default:profile}
requirements:
id: \d+
Action in your controller :
public function profileAction($id)
{
$product = $this->getDoctrine()
->getRepository('UserBundle:Product')
->find($id);
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$id
);
}
return $this->render('UserBundle:Default:profile.html.twig', array('product' =>$product));
And a link or something else in your view like that (Hope you use Twig):
Lorem ipsum
It should be work.
EDIT :
For you search feature, i will do a route like that
_profile:
path: /profile
defaults: {_controller:AcmeBundle:Default:profile}
Controller :
public function profileAction(Request $request){
$form = $this->createForm(new SearchType());
$products = null ;
if($request->isMethod('POST')){
$form->handleRequest($request);
$value = ($form['search']->getData());// change de 'search' according to your form
$em = $this->getDoctrine()->getManager() ;
$product = $em->getRepository('UserBundle:Product')->find($value) ;
}
if(!$product) throw $this->createNotFoundException('your message');
return $this->render('UserBundle:Default:profile.html.twig',array(
'product' => $product
));
}
And finally, your form in the view :
<form method="POST" action="{{ path('_profile') }}">
//your code
</form>
Well i think that here $id become null and it causes error because $id is used to fetch data from your db, so set default value for $id check $id will never become null or empty. All the best.
I do built me a custom constraint validator. The validator is working. But how can I translate the error messages of the CUSTOM validator in a php template? The other validator messages are working, so I do have the translation in app/config/validators.XX.yml.
In my action:
$form = $this->createFormBuilder()
->add('date_id', 'choice', array(
....
'constraints' => array(new CheckChoicesDateId(array('date_ids' => $date_ids))),
....
))
in Bundle/Validator/Constraints
class CheckChoicesDateId extends Constraint
{
public $invalidMessage = '{{ value }}';
public $date_ids;
public function __construct($options = null)
{
parent::__construct($options);
if (null === $this->date_ids ) {
throw new MissingOptionsException('Option date_ids must be given for constraint ' . __CLASS__, array('date_ids'));
}
}
}
in Bundle/Validator/Constraints
class CheckChoicesDateIdValidator extends ConstraintValidator {
public function validate($value, Constraint $constraint) {
if ($value == NULL || !isset($value)) {
$this->context->addViolation($constraint->invalidMessage, array(
'{{ value }}' => 'error.date.0',
//I also tried $this->get('translator')->trans('error.date.0');
// with the error message: Call to undefined method GET
));
}
if (is_numeric($value)) {
$t = array_key_exists($value, $constraint->date_ids);
if ($t == NULL) {
$this->context->addViolation($constraint->invalidMessage, array(
'{{ value }}' => 'error.date.1',
));
}
}
return;
}
}
In my template:
<?php echo $view['form']->errors($form['date_id']) ?>
//I also tried
<?php echo $this->get('translator')->trans($view['form']->errors($form['date_id'])) ?>
I do have a solution, but I guess it is not nice:
In the action I do pass for each possible error a variable.
'constraints' => array(new CheckChoicesDateId(array('date_ids' => $date_ids, 'error_date_0 => $this->get('translator')...., 'error_date_1 => $this->get('translator').... ))),
and in the custom validator I call for each error the right variable with $constraint->error_date_X.
Not nice, but it is working. If anybody has a better solution, feel free to post it!
We upgraded from Symfony 2.0 to 2.1. With 2.0, I used to modify the entity and reload the form like this:
$form->setData($entity);
But this is not allowed anymore with Symfony 2.1 (https://github.com/symfony/symfony/pull/3322). I get the following error:
You cannot change the data of a bound form
Is there a way to rebind the form to the entity/reload the data?
I did something that did the trick… Don't know if it's best way but…
public function contactAction(Request $request){
$task = new myBundle();
$form = $this->createFormBuilder($task)
->add('email', 'text', array('label'=>'E-mail'))
->add('message', 'textarea')
->add('newsletter', 'checkbox', array('label'=>'blabla','required'=>false))
->getForm();
$cloned = clone $form;
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
[... code ...]
$form = $cloned;
}
}
return $this->render(
'myBundle:Default:contact.html.twig',
array('form' => $form->createView())
);
}
By cloning the just instanciated form object, I can switch the «full» one by the empty one, and keep all the params.
And the most obvious way to reset the form after a successful post. Set a "flash", redirect to the form page and display the flash:
public function contactAction(Request $request)
{
$contact = new Contact();
$form = $this->createForm(new ContactType(), $contact);
$form->handleRequest($request);
if ($form->isValid()) {
//...
$session = $this->container->get('session');
$session->getFlashBag()->set('success', 'Your message has been sent.');
return $this->redirect($this->get('router')->generate('contact'));
}
return array(
'form' => $form->createView(),
);
}
And in your twig:
{% if app.session.flashBag.has('success') %}
{{ app.session.flashBag.get('success')[0] }}
{% endif %}
Well, you could create a new instance of the form and re-bind. Seems like overkill, but it would work in a pinch.