Actually there's no request sent as if the function isnt even executed
it already shows in the logs that it uses POST/SponsorNew and doesn't load "SponsorListPage"
after submitting save it in the database
besides i applied the same code on another entity from the same project and it worked
//Add method
/**
* #Route("/sponsorNew",name="newSponsorPage")
*/
public function newSponsor(Request $req):Response{
//1.Create form view
$sponsor= new Sponsor();
//1.b prepare the form
$form= $this->createForm(SponsorType::class, $sponsor);
//2. Handel http request sent by the user
$form=$form->handleRequest($req);
//2.b check the form
if($form->isSubmitted() && $form->isValid()){
//3.Persist data
$em=$this->getDoctrine()->getManager();
$em->persist($sponsor);
$em->flush();
return $this->redirectToRoute("SponsorListPage");
}
//1.c render the form
return $this->render('sponsor/new.html.twig',[
'f'=>$form->createView()
]);
}
and here is the Form
class SponsorType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('nom')
->add('email')
->add('numContact')
->add('type')
->add('sponsor_save', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Sponsor::class,
]);
}
}
here is the template to fill the blanks
<div class="container">
<h1>Add new Sponsor</h1>
{{ form_start(f) }}
<div class="form-group">
<label>
Name of the Sponsor
</label>
{{ form_widget(f.nom,{'attr':{'class':'form-control'}}) }}
</div>
<div class="form-group">
<label>
Email of Sponsor
</label>
{{ form_widget(f.email,{'attr':{'class':'form-control'}}) }}
</div>
<div class="form-group">
<label>
Contact Number
</label>
{{ form_widget(f.numContact,{'attr':{'class':'form-control'}}) }}
</div>
<div class="form-group">
<label>
Type
</label>
{{ form_widget(f.type,{'attr':{'class':'form-control'}}) }}
</div>
{{ form_widget(f.sponsor_save,{'attr':{'class':'btn btn-sm btn-success'}}) }}
{{ form_end(f) }}
</div>
Related
I search a solution to customize the label of choice of EntityType.
Entities
Post
class Post
{
// ...
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Item", cascade={"persist"})
*/
private $items;
// ...
}
Item
class Item
{
// ...
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=127)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="image", type="string", length=255, nullable=true)
*/
private $image;
// ...
public function __toString(){
return $this->title;
}
}
Form
class PostType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('items', EntityType::class, array(
'class' => 'AppBundle\Entity\Item',
'multiple' => true,
'expanded' => true,
))
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Post'
));
}
}
Result
I know how to modify the DOM to get :
<ul>
<li>
<input type="checkbox" id="post_items_1" name="post[items][]" value="1">
<label for="post_items_1">Item 1</label>
</li>
<li>
<input type="checkbox" id="post_items_2" name="post[items][]" value="2">
<label for="post_items_2">Item 2</label>
</li>
<!-- ... -->
</ul>
But I would like get other informations from the Item choices (like property image) :
<ul>
<li>
<input type="checkbox" id="post_items_1" name="post[items][]" value="1">
<label for="post_items_1">
Item 1
<img src="/uploads/item/lorem.jpg" alt="" /> <!-- path store into item #1 -->
</label>
</li>
<li>
<input type="checkbox" id="post_items_2" name="post[items][]" value="2">
<label for="post_items_2">
Item 2
<img src="/uploads/item/ipsum.jpg" alt="" /> <!-- path store into item #2 -->
</label>
</li>
<!-- ... -->
</ul>
Does anyone have a solution?
Setting a choice_label is what you're looking for:
$builder->add('users', EntityType::class, array(
'class' => 'AppBundle:User',
'choice_label' => 'username',
));
Source: http://symfony.com/doc/current/reference/forms/types/entity.html
If you want to use images in your label, you can customize your form template. You can read about it here:
http://symfony.com/doc/current/cookbook/form/form_customization.html#cookbook-form-theming-methods
http://symfony.com/doc/current/book/forms.html#form-theming
I can't store value to database if use Embedded Controller, if I don't use embedded controller I can store it.
Entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="tbl_mail")
*/
class Mail
{
/**
* #ORM\Column(type="string", length=255)
*/
public $email;
}
Controller:
class SendContactController extends Controller
{
public function Email(Request $request)
{
$mail = new Mail();
$form = $this->createFormBuilder($mail)
->add('email','email')
->getForm();
$form->handleRequest($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($mail);
$em->flush();
//return $this->redirectToRoute('');
}
return $this->render('frontend/mail.html.twig', array('form' => $form->createView()));
}
}
View (twig template):
<div>
{{ form_start(form) }}
{{ form_widget(form.email) }}
<input type="submit" class="btn btn-primary" value="OK" />
{{ form_end(form) }}
</div>
i render this controller in my base.html.twig
{%render(controller('AppBundle\Controller\FrontEnd\SendContactController::Email ')) %}
when I press ok to submit nothing happens.
In my application's admin panel, I am showing a list of users who are currently marked as "Active" in the database.
<ul class="list-group">
{% for activeuser in activeusers %}
<li class="list-group-item">
{{ activeuser.username|e }}
<input type="checkbox" name="my-checkbox" class="ckbx" checked>
</li>
{% endfor %}
</ul>
As you can see, each active user list item has a placeholder checkbox for now which is checked when the user is, you guessed it, active.
I would like to be able to simply uncheck the checkbox, and then run an AJAX call to update the database to mark the user as inactive. My first instinct was to create a form for each user object in my controller, but it seems like that would get incredibly messy. Also, I can't simply pass in a
'form' => $form->createView()
from my controller as there presumably has to be one form for each user. Any of the documentation I have read on the subject doesn't seem to provide any help for this particular problem.
UPDATE
I created a function within my controller to create a generic user update form:
/**
* Creates a form to create a User entity.
*
* #param User $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
public function createUserForm(User $entity){
$form = $this->createForm(new UserType(), $entity, array(
'action' => $this->generateUrl('user_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
return $form;
}
The form is generated by the UserType class
class UserType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('isActive', 'checkbox');
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\User'
));
}
/**
* #return string
*/
public function getName()
{
return 'appbundle_user';
}
}
Now inside of the main action (called dashboardAction), I get a list of users and for each of user, generate a form for it. Don't forget to run createView() on each form generation!
public function dashboardAction()
{
$userService = new UserService($this->getDoctrine()->getManager());
$activeUsers = $userService->listUsers('active');
$inactiveUsers = $userService->listUsers('inactive');
$formify_activeUsers = array();
foreach($activeUsers as $activeUser){
$formify_activeUsers[] = $this->createUserForm($activeUser)->createView();
};
return $this->render('AppBundle:Admin:dashboard.html.twig',
array('page_title' => 'Administration Panel',
'activeusers' => $formify_activeUsers,
)
);
}
Then the twig code looks like this:
<ul class="list-group">
{% for activeuser in activeusers %}
<li class="list-group-item">
{{ form_start(activeuser) }}
{{ form_widget(activeuser) }}
{{ form_end(activeuser) }}
</li>
{% endfor %}
</ul>
If what you really want is to activate/desactivate an user why put the overhead of the forms in this situation.
You could simply create an action:
/**
* #Route("/admin/isactive", name="isactive")
* #Method("POST")
*/
public function deactivateUserAction($id){
$em = $this->getDoctrine();
$user= $em
->getRepository('AppBundle\Entity\User')
->find($id);
if (!$user) {
throw $this->createNotFoundException(
'No userfound for id '.$id
);
}
$user->setActive(false);
$em->getManager()->flush($user);
return new JsonResponse();
}
On your view:
<ul class="list-group">
{% for activeUser in activeusers %}
<li class="list-group-item">
<input class="user-status" type="checkbox" value="{{activeUser.id}}">{{activeUser.name}}
</li>
{% endfor %}
</ul>
Attach a on click event into your checkboxs.
$('.user-status).on('click', function(e){
$.post("{{ path('isactive') }}", {userId: $(this).val()})
.done(function(data){
alert("Data loaded: " + data);
});
});
I am having two entity files one as Activite.php and another as Mesurage.php.
Now i want to display an Activite form with 3 fields typeActivite, emplacement and mesurage. the mesurage will be a selection that will fetch data from mesurage table. here is the code that i wrote inside Activite.php to create a many_to_one field for mesurage_id
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="GestionEnvironnementale\ISO14001Bundle\Entity\Mesurage")
*/
private $mesurage;
Below is my Form generation Code :
class ActiviteType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('typeActivite'),
->add('emplacement'),
->add('mesurage', 'entity', array('class' => 'ISO14001Bundle:Mesurage'));
}
}
here is my form code :
<div class="well">
<form method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<br/> <input type="submit" value="Envoyer" class="btn btn-primary" />
</form>
<script src="{{ asset('js/jquery-2.1.1.min.js') }}"></script>
<script type="text/javascript">
$(document).ready(function()
{
var $container3 = $('div#gestionenvironnementale_iso14001bundle_activitetype_activiteMesurage');
var $lienAjout3 = $('Ajouter un mesurage');
$container3.append($lienAjout3);
$lienAjout3.click(function(h) {
ajouterMesurage($container3);
h.preventDefault();
return false;
});
var index3 = $container3.find(':input').length;
if (index3 == 0) {
ajouterMesuragePolluant($container3);
} else {
$container3.children('div').each(function() {
ajouterLienSuppression3($(this));
});
}
function ajouterMesurage($container3) {
var $prototype3 = $($container3.attr('data-prototype').replace(/__name__label__/g, 'Mesurage n°' + (index3+1))
.replace(/__name__/g, index3));
ajouterLienSuppression3($prototype3);
$container3.append($prototype3);
index3++;
}
function ajouterLienSuppression3($prototype3) {
$lienSuppression3 = $('Supprimer');
$prototype3.append($lienSuppression3);
$lienSuppression3.click(function(h) {
$prototype3.remove();
h.preventDefault();
return false;
});
}
});
the code works very well but I dont want to display the list of Mesurage, I want to display the form of Mesurage to add a new !!
If you want to display a form even for mesurage, you have to take a look at embed form
So, basically, you have to create a FormType for mesurage (call it MesurageFormType) and modify your ActiviteType as follows
class ActiviteType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('typeActivite'),
->add('emplacement'),
->add('mesurage', 'collection', array(
'type' => new MesurageFormType(),
'allow_add' => true,));
}
}
This should be fine but if you want to render in a different way your form you should use prototype and jquery
I'm implementing a custom form type that provides an autocomplete field to select a location (country,city or spot). The form type creates two fields, one text field for the autocomplete search input and one hidden field to hold the selected id of the selected location.
When typing into the text field, a server call is made and results are displayed via jquery autocomplete. If a location is selected, the id of the selected location is written to the hidden field whereas the name of the location is displayed in the text field. On the server, I use a client transformer to lookup the entity of the id passed by the hidden field. The text field is ignored.
My model class defines a location field with a property to write back the location entity annotated with a NotNull validation constraint.
Everything works perfectly fine so far but if I do not select a location, the validation message "This value should not be null." is displayed two times.
The bundle is public and can be found in my github repo. The relevant classes are the LocationFieldType and the LocationDataTransformer and the form theme.
And now for how I'm integrating the form type into my project. I added the whole code, sorry for the mass;)
In the model, I define the property as following:
class JourneyCreate
{
/**
* #Assert\NotNull()
* #Assert\Choice(choices = {"offer", "request"})
*/
public $type;
/**
* #Assert\NotNull()
* #Assert\Date()
*/
public $date;
/**
* #Assert\NotNull()
* #Assert\Time()
*/
public $time;
/**
* #Assert\NotNull()
*
*/
public $start;
/**
* #Assert\NotNull()
*
*/
public $destination;
public function buildJourney(User $owner)
{
switch($this->type)
{
case 'offer':
$journey = new JourneyOffer();
break;
case 'request':
$journey = new JourneyRequest();
break;
default:
throw new \InvalidArgumentException('Invalid journey type');
}
$journey->setDate($this->date);
$journey->setTime($this->time);
$journey->addStation(new JourneyStation($this->start));
$journey->addStation(new JourneyStation($this->destination));
$journey->setOwner($owner);
return $journey;
}
}
And in the main form I add the field as following:
class JourneyCreateType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('type','choice', array(
'choices' => array(
'offer' => 'Driver',
'request' => 'Passanger',
),
'empty_value'=>'',
'multiple' => false,
'expanded' => true,
))
->add('date','date',array(
'widget' => 'single_text',
'format' => $this->getDateFormat(\IntlDateFormatter::TRADITIONAL),
))
->add('time','time',array(
'widget' => 'single_text',
))
->add('start','room13_geo_location')
->add('destination','room13_geo_location')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\DemoBundle\Form\Model\JourneyCreate',
));
}
public function getName()
{
return 'journey_create';
}
}
And the controller code:
/**
* #Route("/create/{type}", defaults={"type" = null})
* #Template()
*/
public function createAction($type=null)
{
if($type !== null && !in_array($type,array('request','offer')))
{
throw new NotFoundHttpException();
}
$journeyCreate = new JourneyCreate();
$journeyCreate->type = $type;
$form = $this->createForm(new JourneyCreateType(),$journeyCreate);
if($this->isPost())
{
$form->bind($this->getRequest());
if($form->isValid())
{
$journeyCreate = $form->getData();
$journey = $journeyCreate->buildJourney($this->getCurrentUser());
$this->persistAndFlush($journey);
return $this->redirect($this->generateUrl('acme_demo_journey_edit',array('id'=>$journey->getId())));
}
}
return array(
'form' => $form->createView(),
);
}
And finaly the template code to display the form:
{% block page_body %}
<form class="form-horizontal" action="{{ path('acme_demo_journey_create') }}" method="post" novalidate>
{{form_widget(form)}}
<div class="form-actions">
<button class="btn btn-primary" type="submit">{{'form.submit'|trans}}</button>
{{'form.cancel'|trans}}
</div>
</form>
{% endblock %}
I'm having the theory that this could be because I use two form fields but don't know how to fix this. Any suggestions about how to solve this more elegant are welcome.
As complicated as this question might look, the answer is as simple as removing the {{form_errors(form)}} from the widget template block. Because the *form_row* block looks like:
{% block form_row %}
{% spaceless %}
<div class="form_row">
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
The error was simply outputted two times.