I'm trying to create simple form but for some reason input fields are not rendered. The source code shows that the open and close tag of form are rendered but not the input fields itself.
Here is the code
namespace SDProjectBundle\Forms;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class UserForm extends AbstractType
{
public function formBuilder(FormBuilderInterface $builder, array $options)
{
$builder->add('email', 'text')
->add('password', 'password')
->add('Send', 'submit');
}
public function getName()
{
return 'app_users';
}
}
namespace SDProjectBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use SDProjectBundle\Forms\UserForm;
use SDProjectBundle\Entity\User;
class UsersController extends Controller
{
public function addAction(Request $request)
{
$form = $this->createForm(new UserForm(), new User());
return $this->render('SDProjectBundle:Users:add.html.twig', array(
'form' => $form->createView(),
));
}
}
add.html.twig
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
What I'm doing wrong?
You implements the wrong method in the form class: you need to implements the buildForm method of your custom form type.
Practically, in the UserForm class, you need to put this:
public function buildForm(FormBuilderInterface $builder, array $options)
instead of
public function formBuilder(FormBuilderInterface $builder, array $options)
Hope this help
If you want to render the form component try with
{{ form_widget(form) }}
instead of
{{ form_label(form) }}
If you want to render only the label of the field you need to specify the field as:
{{ form_label(form.email) }}
A complete manually rendered version of your form can be:
{{ form_start(form) }}
{{ form_errors(form) }}
<div>
{{ form_label(form.email) }}
{{ form_errors(form.email) }}
{{ form_widget(form.email) }}
</div>
<div>
{{ form_label(form. password) }}
{{ form_errors(form. password) }}
{{ form_widget(form. password) }}
</div>
<div>
{{ form_widget(form. Send) }}
</div>
{{ form_end(form) }}
Try this in your TWIG:
{% block form_row %}
{% spaceless %}
<div class="form-group">
{{ form_label(form) }}
<div>
{{ form_widget(form) }}
</div>
</div>
{% endspaceless %}
{% endblock form_row %}
Related
I am trying to create a simple form within Symfony. Not quite sure why this is not grabbing the form variable.
Receiving error:
Variable "form" does not exist src/Thinkfasttoys/MapWatchBundle/Resources/views/Default/createMapPolicy.html.twig at line 30
Controller - DefaultController.php
class DefaultController extends Controller
{
public function policyFormAction()
{
$form = $this->createFormBuilder()
->add('name', 'text')
->add('age', 'integer')
->add('save', 'submit')
->getForm()
;
return $this->render('ThinkfasttoysMapWatchBundle:Default:createMapPolicy.html.twig', array(
'form' => $form->createView(),
));
}
View - createMapPolicy.html.twig
{% block body %}
<div class="row-fluid">
<div class="span12">
<div class="widget-box">
<h4 align="center", padding="10px 0 10px 0">Create a New MAP Policy</h4>
{{ form(form) }}
<div class="container-1">
</div><!-- /.container -->
</div><!-- /.widgetbox -->
</div>
</div>
{% endblock %}
In twig you have to display the form like this:
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
I am doing a web application with symfony3 and I need a way to let the users to edit and update their profile. I used FosUserBundle to manage the the users access but i don't know what steps to take to solve my problem.
Does someone have some ideas or useful links to share ?
thank you
I Solved the problem. Yes it's my first question on stackoverflow and I'm learning.
here is my code:
dogController.php
/**
* #Route("/profile/edit", name= "edit_profile" )
*/
public function edit_profileAction(Request $request)
{
$user = $this->getUser();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isValid()) {
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
$event = new FormEvent($form, $request);
$dispatcher = $this->get('event_dispatcher');
$dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
//$url = $this->generateUrl('fos_user_profile_show');
$url = $this->generateUrl('edit_profile');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
$this->get('session')->getFlashBag()->add(
'notice',
'Profile Updated!'
);
return $response;
}
return $this->render('dog/edit_profile.html.twig',array('form'=>$form->createView()));
}
UserType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Vich\UploaderBundle\Form\Type\VichImageType;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Form\Extension\Core\Type\FileType;
class UserType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array $options){
$builder->add('username')
->add('name')
->add('surname')
->add('email')
->add('telephone')
->add('imageFile', FileType::Class );
}
public function setDefaultOptions(OptionsResolverInterface $resolver){
$resolver->setDefaults( array('data_class' => 'AppBundle\Entity\User') );
}
public function getName() {
return 'appBundle_user';
}`enter code here`
}
edit_profile.html.twig
<header>
<div class="container">
<div class="row">
<div class="col-lg-12">
<h2 class="name">Edit Profile</h2>
<div class="row" >
<div class="col-lg-12">
<div class="input_width" >
{% for flashMessage in app.session.flashbag.get('notice') %}
<div class="alert alert-success alert">
{{ flashMessage }}
</div>
{% endfor %}
{{form_start(form, {'attr': {'class': 'form-horizontal'}} )}}
{{ form_errors(form) }}
<div class="form-group">
{{ form_label(form.username) }}
{{ form_errors(form.username) }}
{{ form_widget(form.username , {'attr': {'class': 'form-control'}} ) }}
</div>
<div class="form-group">
{{ form_label(form.email) }}
{{ form_errors(form.email) }}
{{ form_widget(form.email , {'attr': {'class': 'form-control'}} ) }}
</div>
<div class="form-group">
{{ form_label(form.name) }}
{{ form_errors(form.name) }}
{{ form_widget(form.name , {'attr': {'class': 'form-control'}} ) }}
</div>
<div class="form-group">
{{ form_label(form.surname) }}
{{ form_errors(form.surname) }}
{{ form_widget(form.surname, {'attr': {'class': 'form-control'}}) }}
</div>
<div class="form-group">
{{ form_label(form.telephone) }}
{{ form_errors(form.telephone) }}
{{ form_widget(form.telephone, {'attr': {'class': 'form-control'}}) }}
</div>
<div class="form-group">
{{ form_label(form.imageFile) }}
{{ form_errors(form.imageFile) }}
{{ form_widget(form.imageFile) }}
</div>
<input type="submit" value="Submit" class="btn btn-default bluInput " />
{{form_end(form)}}
</div>
</div>
</div>
</div>
</div>
</div>
</header>
Basically I had to create a form type class linked to my entity, then, use it in my controller as long as the Fos user bundle user manager.
I'm trying to override field appearance.
I created my custom form type:
namespace AppBundle\Form\Type\Frontend\Search;
/**/
class TripTypeType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'choices' => [
'One-way',
'Round-trip',
],
'multiple' => false,
'expanded' => true,
'required' => false,
'empty_value' => false,
]);
}
/**
* {#inheritdoc}
*/
public function getParent()
{
return ChoiceType::class;
}
}
After that i added this field to parent form:
namespace AppBundle\Form\Type\Frontend\Search;
/***/
class FlightSearchType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tripType', TripTypeType::class)
->add('airports', AirportsType::class)
->add('flightAt', FlightDatesType::class)
->add('flightClass', FlightClassType::class);
}
}
And rendering this field like that:
{% for type in form.tripType %}
{% if loop.index == 1 %}
{% set way_id = 'one-way' %}
{% else %}
{% set way_id = 'round-trip' %}
{% endif %}
{{ form_widget(type, {
'id': way_id,
'attr': {'class': 'tabs-way__radio'},
'label_attr': {'class': 'tabs-way__label', 'for': way_id}
}) }}
{% endfor %}
So what i want to get is a:
<div class="tabs-way__item">
<input type="radio" id="one-way" name="flight_search[tripType]" class="tabs-way__radio" value="0">
<label class="tabs-way__label" for="one-way">One-way</label>
</div>
For that i'm trying to override widget for this field:
{# app/Resources/views/Form/fields.html.twig #}
{% block trip_type_widget %}
<div class="tabs-way__item">
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
{{ block('form_label') }}
</div>
{% endblock trip_type_widget %}
And i include that file in config.yml in twig section. But all i get it's nothing :(
If you need to override custom field, you have to prefix it with underscore, e.g.:
{% block _trip_type_widget %}
<div class="tabs-way__item">
{{- form_label(form) -}}
{{- form_widget(form) -}}
{{- form_errors(form) -}}
</div>
{% endblock _trip_type_widget %}
I am using Symfony2 2.6.4 with the FOS User Bundle (master) and I am having a hard time trying to pass a partial registration from the home page to the registration page.
The Goal
I want a user to start on the home page and fill out some info and press submit. I want the user to be passed to the registration page and pre fill the items that they have already filled out on the front page.
Things I have tried:
I am unsure what is feasable and have already spend too much time on this. I tried extending the registration controller but I am getting errors before I can even start on my issue so I stopped. My last thought was to pass the variables in a session to the overridden registration form type and see if I can pre-populate it there.
Has anyone done anything like this before? They sure don't make it easy.
Credit goes to #NawfalSerrar Thank you for the idea. I was close but not close enough!
So what I ended up doing was this.
This is the controller action that does that work.
/**
* #Route("/", name="Home")
*/
public function indexAction(Request $request)
{
$form = $this->createForm(new RegisterFormType());
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$user = new User();
$session = $this->get('session');
$registration = array();
$registration['firstName'] = $data['first'];
$registration['lastName'] = $data['last'];
$registration['middleInit'] = $data['middle'];
$registration['email'] = $data['email'];
$session->set('registration', $registration);
return $this->redirect($this->generateUrl("fos_user_registration_register"));
}
return $this->render('Bundle:Page:index.html.twig', array(
'form' => $form->createView(),
));
}
Then the form on the front end.
{{ form_start(form,{'attr': {'class': 'reg-page'}}) }}
<div class="reg-header">
<h1>Get Started!</h1>
<p>Already Signed Up? Click Sign In to login
your account.</p>
</div>
{{ form_errors(form) }}
<div class="row">
<div class="col-sm-6">
{{ form_label(form.first) }}
{{ form_widget(form.first, {'attr': {'class': 'form-control margin-bottom-10'}}) }}
</div>
<div class="col-sm-6">
{{ form_label(form.middle) }}
{{ form_widget(form.middle, {'attr': {'class': 'form-control margin-bottom-10'}}) }}
</div>
<div class="col-sm-6">
{{ form_label(form.last) }}
{{ form_widget(form.last, {'attr': {'class': 'form-control margin-bottom-10'}}) }}
</div>
</div>
{{ form_label(form.email) }}
{{ form_widget(form.email, {'attr': {'class': 'form-control'}}) }}
<div class="row">
<div class="col-lg-6 text-right">
{{ form_widget(form.save, {'attr': {'class': 'btn-u'}}) }}
</div>
</div>
{{ form_end(form) }}
Registration page looks like this.
{% extends '::base.html.twig' %}
{% block body %}
{% set tokens = app.session.get('registration') %}
{% if tokens['firstName'] is defined %}
{% set firstName = tokens['firstName'] %}
{% endif %}
{% if tokens['middleInit'] is defined %}
{% set middleInit = tokens['middleInit'] %}
{% endif %}
{% if tokens['lastName'] is defined %}
{% set lastName = tokens['lastName'] %}
{% endif %}
{% if tokens['email'] is defined %}
{% set email = tokens['email'] %}
{% endif %}
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_label(form.firstName, 'First Name', {label_attr: {class: 'foo'}}) }}
{% if firstName is defined %}
{{ form_widget(form.firstName, { attr: {class: 'TestClass'}, value : firstName }) }}
{% else %}
{{ form_widget(form.firstName, { attr: {class: 'TestClass'} }) }}
{% endif %}
{{ form_label(form.middleInitial) }}
{% if middleInitial is defined %}
{{ form_widget(form.middleInitial, { attr: {class: 'TestClass'}, value : middleInit }) }}
{% else %}
{{ form_widget(form.middleInitial, { attr: {class: 'TestClass'}}) }}
{% endif %}
{{ form_label(form.lastName) }}
{% if lastName is defined %}
{{ form_widget(form.lastName, { attr: {class: 'TestClass'}, value : lastName }) }}
{% else %}
{{ form_widget(form.lastName, { attr: {class: 'TestClass'}}) }}
{% endif %}
{{ form_label(form.email) }}
{% if email is defined %}
{{ form_widget(form.email, { attr: {class: 'TestClass'}, value : email }) }}
{% else %}
{{ form_widget(form.email, { attr: {class: 'TestClass'}}) }}
{% endif %}
{{ form_label(form.plainPassword.first) }}
{{ form_widget(form.plainPassword.first) }}
{{ form_label(form.plainPassword.second) }}
{{ form_widget(form.plainPassword.second) }}
<div>
<input type="submit" value="{{ 'registration.submit'|trans }}"/>
</div>
{{ form_end(form) }}
{% endblock %}
Hope this helps!
I have a ProfileType Form in my UserBundle (extending from SonataUserBundle), in the ProfileType Form I added a sub form type (AddressType()).
ProfileType
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('gender')
->add('firstname')
->add('lastname')
->add('middlename')
->add('dateOfBirth', 'birthday', array('required' => false))
->add('phone')
->add('address', new AddressType(), array('required' => false));
;
}
/**
* {#inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => $this->class,
'validation_groups' => array('Profile', 'Address'),
'cascade_validation' => true,
));
}
AddressType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('postalcode')
->add('houseNumber')
->add('houseNumberAddition')
->add('street')
->add('city')
->add('country')
;
}
In the edit_profile_html.twig I like to know if there are any errors specifically in the AddressType. But form.address.vars.errors does not return the number of invalid elements in AddressType. If I specifically check the errors for a element in AddressType it does return the correct count.
So: form.address.vars.errors.length is 0, but form.address.postalcode.var.errors.length work. But I do not want to check for all elements one by one.
<fieldset {% if form.address.vars.errors|length>0 %} class="warning" {% endif %} >
<legend>{% trans %}vg.userbundle.form.address.legend{% endtrans %}</legend>
{{ form_rest(form.address) }}
</fieldset>
edit_profile_html.twig
{% block subtitle %}{{ "title_user_account" | trans({}, 'SonataUserBundle') }} - {{ "title_user_edit_profile" | trans({}, 'SonataUserBundle') }}{% endblock %}
{% block content %}
{% block fos_user_content %}
<form novalidate action="{{ path('sonata_user_profile_edit') }}" method="POST">
<fieldset {% if form.vars.errors|length>0 %} class="warning" {% endif %} >
<legend>{% trans %}vg.userbundle.form.profile.legend{% endtrans %}</legend>
{{ form_row(form.gender) }}
{{ form_row(form.firstname) }}
{{ form_row(form.lastname) }}
{{ form_row(form.middlename) }}
{{ form_row(form.dateOfBirth) }}
{{ form_row(form.phone) }}
</fieldset>
<fieldset {% if form.address.vars.errors|length>0 %} class="warning" {% endif %} >
<legend>{% trans %}vg.userbundle.form.address.legend{% endtrans %}</legend>
{{ form_rest(form.address) }}
</fieldset>
<fieldset class="submit">
<ul>
<li><input type="submit" name="submit"
value="{{ 'sonata_user_submit'|trans({}, 'SonataUserBundle') }}"/></li>
</ul>
</fieldset>
</form>
{% endblock %}
{% endblock content %}
So what is the correct way to retrieve the number of invalid elements of an 'embedded' FormType?
You can check if a form and all of its elements are valid (=have no errors) using the "valid" variable (which I guess is what you want to do):
<fieldset {% if not form.address.vars.valid %} class="warning" {% endif %} >
I suppose there is no way round to iterate through the object address and count the errors of child items.
{% for child in address %}
{{ ...count errors... }}
{% endfor %}
Note that every form item is an object which means that every child of "address" is an object as well.