Display Twig Form with a loop - forms

I'm currently working on a private social network for fun and to improve my skills.
Anyway, I want to display a form to leave a comment on a post using a loop but I have issues trying that.
I'm using Symfony, twig and bootstrap, and I'd like to keep js, jquery or ajax away.
Here is my code:
My form builder:
class CommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', null, [
"label" => "Your title"
])
->add('content', null, [
"label" => "Your content"
])
->add('submit', SubmitType::class, [
"label" => "Publish your shitty comment!"
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class,
]);
}
}
and my view:
<ul class="nav col-4 offset-3">
{% for post in posts %}
<li class="postItem">
<article class="postItem">
<p> {{ post.title }} </p>
<img id="postPics" src="{{ asset('./pictures/posts/' ~ post.picture) }}">
{{ form(leaveCommentForm) }}
<h3>{{ post.title }}</h3>
<p>{{ post.content }}</p>
<author>{{ post.user.username }}</author>
<div class="commentPost">
{% for comment in post.comments %}
<article>
<h6 style="font-weight: bold">{{ comment.title }} -
By
<author>{{ comment.user.username }}
on {{ comment.dateCreated | date('Y-M-d') }}</author>
</h6>
<p>{{ comment.content }}</p>
</article>
{% endfor %}
</div>
<input type="hidden" value="{{ post.id }}" name="postId"> {{ post.id }}
<button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Leave a comment
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">Leave a comment</h4>
</div>
<div class="modal-body">
{{ form_start(leaveCommentForm) }}
<input type="hidden" value="{{ post.id }}" name="postId"> {{ post.id }}
{{ form_end(leaveCommentForm) }}
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</article>
</li>
{% endfor %}
</ul>
As you can see I want to display my form on each iteration of post (with or without modal I don't really care I was just trying some things).
My problems here are:
*If I use a modal, I can't get my post.id inside my modal and so I can't send it to my controller.
Actually I get the value of first post.id for every posts.
*If I don't use a modal I can't even see my form on my page.
If you have a solution that would be great!
Thanks in advance guys!

Related

How to shift a Bootstrap form over to the right?

I am doing an inventory management page for my school project, and currently, the form whihroducts is shifted to the left.
How it looks like:
{% extends "base.html" %}
{% block title %}Adding a new product{% endblock %}
{% block content %}
{% from "includes/formHelper.html" import render_field %}
<h1 class="display-4">Add new product</h1>
<form method="POST" action="">
<!-- Container class for Form -->
<div id="container py-2">
<div class="form-group" >
<div class="col-sm-3 order-5 float-right py-2">
{{ render_field(form.name, class="form-control") }}
</div>
</div>
<div class="form-group">
<div class="col-sm-3 order-5 float-right py-2">
{{ render_fiel {{ render_field(form.type, class="form-control") }}
</div>
</div>
<div class="form-group">
<div class="col-sm-3 order-5 float-right py-2">
d(form.stock, class="form-control") }}
</div>
</div>
<div class="form-group">
<div class="col-sm-3 order-5 float-right py-2">
{{ render_field(form.price, class="form-control") }}
</div>
</div>
</div>
<input type="submit" value="Submit" class="btn btn-success btn-lg float-left">
</form>
I tried using CSS to float-right and row-reverse the entire form to the right of the page, but it still does not work out.

symfony 3.4 pass variable to a modal in twig

I need help to solve my problem. I have a page with my list of "equipos". Every "equipo" in the table has an Edit buttom, and the page show another buttom to add new "equipos".
So far I manage to call a modal for NEW using the {{ render() }} syntax, the equipoNewModal works fine because is an "static" route (/equipo/new) in Symfony; but the EDIT don't work because I can't pass the "equipo" variable to the equipoEditModal and get the id to complete the route (/equipo/{id}/edit) and call the controller.
Symfony can't render the page and return an error: Variable "equipo" does not exist.
The controller isn't the problem, if I create an tag with href={{ path('edit_equipo', {'id': equipo.id}) }} in the list.html.twig template and skip the modal I can edit every equipo. To dismiss the controller, if I hardcoded the line:
{{ form_start(equipoForm, {'action': path('edit_equipo', {'id': equipo.id})}) }}
in the edit.html.twig to:
{{ form_start(equipoForm, {'action': path('edit_equipo', {'id': 1})}) }}
the edit action works, of course for every equipo the edit action call the edition of the item with id=1 in the database, but it say that the controller works fine.
I'm missing something and hope the community find the solution... sorry my english.
==============
list.html.twig
<table id="datatable-buttoms" class="table table-striped table-bordered">
<thead>
<tr>
<th>ID</th>
<th>EQUIPOS</th>
</tr>
</thead>
<tbody>
{% for equipo in equipos %}
<tr>
<td>{{ equipo.id }}</td>
<td>{{ equipo.equipo }}</td>
<td>{{ equipo.nomenclador }}</td>
<td>{{ equipo.nomenclador.especialidad }}</td>
<td>
<button type="button" class="btn btn-primary" href="" data-toggle="modal" data-target="#equipoEditModal">
Editar
</button>
<button type="button" class="btn btn-danger" href="" data-toggle="modal" data-target="#equipoDeleteModal">
Eliminar
</button>
</td>
</tr>
{{ render(controller('AppBundle:Equipo:edit', {'id': equipo.id})) }}
{% endfor %}
</tbody>
</table>
<button type="button" class="btn btn-primary" href="" data-toggle="modal" data-target="#equipoNewModal">
Agregar
</button>
{{ render(controller('AppBundle:Equipo:new')) }}
=============
new.html.twig
<div class="modal fade" id="equipoNewModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">NUEVO</h4>
</div>
<div class="modal-body">
{{ form_start(equipoForm, {'action': path('new_equipo')}) }}
{{ form_widget(equipoForm) }}
<button type="submit" class="btn btn-primary">Guardar</button>
{{ form_end(equipoForm) }}
</div>
</div>
</div>
</div>
==============
edit.html.twig
<div class="modal fade" id="equipoEditModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">EDITAR</h4>
</div>
<div class="modal-body">
{{ form_start(equipoForm, {'action': path('edit_equipo', {'id': equipo.id})}) }}
{{ form_widget(equipoForm) }}
<button type="submit" class="btn btn-primary">Guardar</button>
{{ form_end(equipoForm) }}
</div>
</div>
</div>
</div>
===============
Edit Controller
/**
* #Route("/equipo/{id}/edit", name="edit_equipo")
*/
public function editAction(Request $request, Equipo $equipo)
{
$form = $this->createForm(EquipoFormType::class, $equipo);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$equipo = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($equipo);
$em->flush();
return $this->redirectToRoute('list_equipos');
}
return $this->render('sysreport/equipos/edit.html.twig', [
'equipoForm' => $form->createView(),
]);
}
EDIT:
To solve the problem only add the line that #Nobady says in the editAction controller...
To call every modal depending of the equipo change data-target in the list.html.twig file:
<button type="button" class="btn btn-primary" href="" data-toggle="modal" data-target="#equipo{{ equipo.id }}">
and of course in the edit.html.twig file too:
<div class="modal fade" id="equipo{{ equipo.id }}">
to solve then you have to pass equipo as parameter, like this in Edit Controller:
/**
* #Route("/equipo/{id}/edit", name="edit_equipo")
*/
public function editAction(Request $request, Equipo $equipo)
{
$form = $this->createForm(EquipoFormType::class, $equipo);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$equipo = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($equipo);
$em->flush();
return $this->redirectToRoute('list_equipos');
}
return $this->render('sysreport/equipos/edit.html.twig', [
'equipoForm' => $form->createView(),
'equipo' => $equipo
]);
}

Submitting a form logs the user out

I'm currently running into a very confusing problem with Symfony 4 (or not even that, I don't know). I've set up a login/registration system manually, which has been working great, up until now. I've developed a form where one can create branches for their main company. I used a FormType for that exact manner:
<?php
// src/Form/UserType.php
namespace App\Form;
use App\Entity\Filiale;
use App\Entity\Kammer;
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\NumberType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class FilialType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('apothekenname', TextType::class)
->add('email', EmailType::class)
->add('anrede', TextType::class)
->add('titel', TextType::class, array(
'required' => false
))
->add('vorname', TextType::class)
->add('name', TextType::class)
->add('adresszusatz', TextType::class, array(
'required' => false
))
->add('strasse', TextType::class)
->add('hausnummer', TextType::class)
->add('plz', NumberType::class)
->add('ort', TextType::class)
//->add('kammer', TextType::class)
->add('kammer', EntityType::class, array(
'class' => Kammer::class,
'choice_label' => 'name',
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Filiale::class,
));
}
}
?>
The view rendering the FormType looks like this, where there's a separate button triggering the Bootstrap modal dialog:
<div class="modal fade" id="modal-add-filiale" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Neue Filialapotheke anlegen</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Schließen">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{{ form_start(form_add_filiale) }}
<div class="form-group row">
<label class="col-xl-3" for="filiale-apothekenname">Apothekenname</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.apothekenname) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-anrede">Anrede</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.anrede) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-titel">Titel</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.titel) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-vorname">Vorname</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.vorname) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-name">Name</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.name) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-strasse">Straße</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.strasse) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-hausnummer">Hausnummer</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.hausnummer) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-adresszusatz">Adresszusatz</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.adresszusatz) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-plz">PLZ</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.plz) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-stadt">Stadt</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.ort) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-email">Email</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.email) }}
</div>
</div>
<div class="form-group row">
<label class="col-xl-3" for="filiale-kammerbezirk">Kammerbezirk</label>
<div class="col-xl-9">
{{ form_widget(form_add_filiale.kammer) }}
</div>
</div>
<button type="submit">Hu</button>
{{ form_end(form_add_filiale) }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Abbrechen</button>
<button id="modal-add-filiale-save" type="submit" class="btn btn-primary">Speichern</button>
</div>
</div>
</div>
</div>
The Controller function processing the form, renderung and submission looks like this:
public function login(Request $request, AuthenticationUtils $authUtils, AuthorizationCheckerInterface $authChecker) {
$isLoggedIn = ($authChecker->isGranted('ROLE_USER') || $authChecker->isGranted('ROLE_USER_MO'));
if($isLoggedIn) {
$filiale = new Filiale();
$form = $this->createForm(FilialType::class, $filiale);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$filiale->setUser($this->getUser());
$em = $this->getDoctrine()->getManager();
$em->persist($filiale);
$em->flush();
return $this->render('default/startpage_loggedin.html.twig', array(
'breadcrumb' => 'BROTKRUMEN',
'form_add_filiale' => $form->createView(),
'toast_finished' => 1,
));
}
return $this->render('default/startpage_loggedin.html.twig', array(
'breadcrumb' => 'BROTKRUMEN',
'form_add_filiale' => $form->createView(),
));
}
else {
// get the login error if there is one
$error = $authUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authUtils->getLastUsername();
return $this->render('default/startpage_loggedout.html.twig', array(
'last_username' => $lastUsername,
'error' => $error,
));
}
}
While the code isn't perfectly arranged and I'm probably missing some best practices, I still find the problem I'm facing weird. The form is only accessible while logged in - when I click the button to open the modal, then fill the form out and then press the submit button, I'm automatically getting logged out and the error message "invalid credentials" is displayed.
However, when I'm outsourcing the form rendering and form handling to a new view and a new controller function, the code does exactly what it's supposed to do, without touching the logged in user.
I'm basically running out of ideas and would appreciate any hint you guys could offer. Thank you in advance!
Edit: Security.yml
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
App\Entity\User:
algorithm: bcrypt
legacy_encoder:
algorithm: md5
encode_as_base64: false
iterations: 1
providers:
in_memory: { memory: ~ }
db_provider:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
#pattern: ^/
#http_basic: ~
anonymous: ~
provider: db_provider
user_checker: App\Security\UserChecker
logout:
path: /logout
target: /
form_login:
login_path: home
check_path: home
access_control:
- { path: ^/motivwelten, roles: ROLE_USER }
- { path: ^/services/.*, roles: ROLE_USER }
- { path: ^/shop, roles: ROLE_USER }
- { path: ^/shop/.*, roles: ROLE_USER }
erase_credentials: false
While not a direct solution to the initial question I asked, I fixed the problem by moving every logic but the login away from the login method in my controller.
This should probably be the better practice anyways. I believe submitting to the /login route tirggers a login event and, as there are no credentials, the service can't verify the user and terminates the session while displaying "invalid credentials" as well.

This form should not contain extra fields. on multile submite button

I have a two part form in symfony2 of a single table db.
On my edit page i display whole form with two save buttons.
when i edit some field and try to save it that shows the extra field error
my controller code is
$form = $this->createForm(new PatientfullType(), $test, array());
$formadd = $this->createForm(new PatientfulladdType(), $test, array());
.
.
if ($form->get('save')->isClicked()) {
return $this->render('AdminBundle:FormsController:patientformfull.html.twig', array('formadd' => $formadd->createView(),'form' => $form->createView() ));
// probably redirect to the add page again
}
else
{
return $this->render('AdminBundle:FormsController:patientformfull.html.twig', array('formadd' => $formadd->createView(),'form' => $form->createView() ));
}
my twig file has two object
form and formadd
<div class="row" style="margin-bottom: 15px;">
<div class="col-xs-3">
{{ form_label(form.sex) }}
</div>
<div class="col-xs-9 col-sm-4 col-md-3">
{{ form_widget(form.sex, {'attr': {'class': 'form-control'}}) }}
</div>
</div>
<div class="row" style="margin-bottom: 15px;">
<div class="col-xs-3">
{{ form_label(formadd.ChronicDiseases) }}
</div>
<div class="col-xs-9 col-sm-4 col-md-3">
{{ form_widget(formadd.ChronicDiseases, {'attr': {'class': 'form-control'}}) }}
</div>
</div>
</div><div class="col-xs-9 col-sm-5">
{{ form_widget(form.save , {'attr': {'class': 'btn btn-success'}}) }}
{{ form_widget(form.cancel , {'attr': {'onclick': 'cancelRedirect()','class': 'btn btn-default'}}) }}
</div>
</div><div class="col-xs-9 col-sm-5">
{{ form_widget(formadd.save1 , {'attr': {'class': 'btn btn-success'}}) }}
</div>

Saving Data from Laravel Form in Bootstrap Modal

i have a bootstrap modal dialog which use laravel form to register a user.
Here's the code:
<div id="addPenggunaModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="ModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="ModalLabel">Tambah Pengguna Baru</h3>
</div>
<div class="modal-body">
{{ Form::open(array('url'=>'users/addpengguna','class'=>'form-horizontal', 'method'=> 'POST')) }}
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
<div class="control-group">
<label for="firstname" class="control-label">First Name:</label>
<div class="controls">
{{ Form::text('firstname', null, array('class'=>'span3', 'placeholder'=>'First Name')) }}
</div>
</div> <!-- /field -->
<div class="control-group">
<label for="lastname" class="control-label">Last Name: </label>
<div class="controls">
{{ Form::text('lastname', null, array('class'=>'span3', 'placeholder'=>'Last Name')) }}
</div>
</div> <!-- /field -->
<div class="control-group">
<label for="email" class="control-label">Email Address: </label>
<div class="controls">
{{ Form::text('email', null, array('class'=>'span3', 'placeholder'=>'Email Address')) }}
</div>
</div> <!-- /field -->
<div class="control-group">
<label for="password" class="control-label">Password:</label>
<div class="controls">
{{ Form::password('password', array('class'=>'span3', 'placeholder'=>'Password')) }}
</div>
</div> <!-- /field -->
<div class="control-group">
<label for="confirm_password" class="control-label">Confirm Password:</label>
<div class="controls">
{{ Form::password('password_confirmation', array('class'=>'span3', 'placeholder'=>'Confirm Password')) }}
</div>
</div> <!-- /field -->
<div class="control-group">
<label for="type_user" class="control-label">Tipe Pengguna:</label>
<div class="controls">
{{ Form::radio('level', '1'); }} Supervisor
{{ Form::radio('level', '0'); }} Sales
</div>
</div> <!-- /field -->
</form>
</div>
<div class="modal-footer">
{{ Form::submit('Simpan', array('class'=>'button btn btn-primary','id'=>'mdl_save_change'))}}
<button class="btn" data-dismiss="modal" aria-hidden="true">Batal</button>
</div>
{{ Form::close() }}
</div>
then i use the controller to save the details:
public function postAddpengguna(){
/* function to add user in data pengguna */
$validator = Validator::make(Input::all(), User::$rules);
if($validator -> passes()){
$user = new User;
$user->firstname = Input::get('firstname');
$user->lastname = Input::get('lastname');
$user->email = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$user->level = Input::get('level');
/* save the following details */
$user->save();
return Redirect::to('pengguna');
} else {
return Redirect::to('index');
}
}
but the form doesn't save any data to database. I have another page called registration and it works.
my questions:
how to trace POST from laravel form submit, is there any browser extension?
how to trace error log in laravel
any ideas what's going on in my problem?
thank you in advance.
UPDATE
Here's the screenshot that describe how this works.
bootstrap modal:
when i press the submit button (blue button in modal) i want it to save the data to db. The function php is shown above.
PS. i don't use any AJAX to call the value from the FORM. But when i use the AJAX, it always error because TOKEN is missing.
First of all check the action and _token field of form . To add token field in your form you should include the following line in your form:
<input type="hidden" name="_token" value="{{csrf_token()}}">
To re-use bootstrap modal in your project you can check this Github link
In the latest versions of laravel 5 you can use a shortcut to get the token field.
<form ... >
{!! csrf_field() !!}
</form>
In this case you'll get something like
<input type="hidden" name="_token" value="hpyL7cUbCMFBGRfCi2dpzE5XHGj8WuyY2jqloKRx">
You can in any case get the token string calling csrf_token(), anyway I honestly prefer the csrf_field() alternative.
You may use this code with your ajax code:
$(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': {!! json_encode(csrf_token()) !!}
}
});
});