I can not send a variable to a twig template - forms

I dont know why not can show a variable, I read the manual and I searched in many websites, but I have no idea what I'm doing wrong...
I have a classType (there is not from a entity), the class form have 3 combobox and a textbox, when I submit the form, another template (show2.html.twig) render the new form where I want show the textbox value... I speend many time and a have 0 result ;)
When I see the Symfony profiler, I can see the values of the form in the "Request POST Parameters" section, but I'cant catch it and show it in the twig template...
that is the code wath dont work for my
$this->get('request')->request->get('campo', 'can not show it ¬¬')
in the template dont show the "campo" value, just "can not show it ¬¬"
this is my classType
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('Pais', 'entity', array(
'class' => 'UnadeniZonaBundle:Pais',
'property' => 'paisnomb',
))
->add('Provincia', 'entity', array(
'class' => 'UnadeniZonaBundle:Provincia',
'property' => 'provnomb',
))
->add('Ciudad', 'entity', array(
'class' => 'UnadeniZonaBundle:Ciudad',
'property' => 'ciudnomb',
))
->add('Campo', 'text', array(
'label' => 'campo',));
}
public function getName() {
return 'ciudad2';
}
}
My controller...
public function newAction(Request $request) {
$form = $this->createForm(new Ciudad2Type());
return $this->render('UnadeniZonaBundle:Ciudad2:new.html.twig', array(
'form' => $form->createView(),
'mensaje' => 'test'
));
}
public function showAction(Request $request) {
if ($request->isMethod('POST')) {
return $this->render('UnadeniZonaBundle:Ciudad2:show2.html.twig', array(
'mensaje' => $this->get('request')->request->get('campo', 'can not show it ¬¬')
));
}
}
this the templates
(new.html.twig)
{% extends '::base.html.twig' %}
{% block content -%}
<form action="{{ path('ciudad2_show') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit" />
{{ mensaje }}
</form>
{% endblock %}
(Show2.html.twig)
{% extends '::base.html.twig' %}
{% block content -%}
{{ mensaje }}
{% endblock %}

If you try this :
$postData = $request->request->get('ciudad2');
$targetValue = $postData['Campo'];
return $this->render('UnadeniZonaBundle:Ciudad2:show2.html.twig', array(
'mensaje' => $targetValue)
));

It's a typo issue. Change campo to Campo in your controller.
if ($this->getRequest()->isMethod('POST')) {
$request = $this->getRequest->request;
$campo = $request->get('Campo', 'cannot show it.', true);
return $this->render('UnadeniZonaBundle:Ciudad2:show2.html.twig', array(
'mensaje' => $campo
));
}

Related

Embedded form render wrong input type

To allow customisation of the registration form, some form fields are generated from database informations and the form in embedded into the registration form.
While each fields of the embedded form is typed, for some reason, when I render them using twig, some types like url or number are rendered as text type input.
Yet, all fields form the main form (nom, prenom, email, plainPassword) are rendered with the assigned type.
As you can see in the code fragments, I'm properly using form_widget and form_widget to render each input, thus type handling is done by Symfony.
When I dump each formView for each field, within field.vars.block_prefixes (array), I can find the type of the input as it should be.
As example, this is the content of a text input :
"block_prefixes" => array:3 [▼
0 => "form"
1 => "text"
2 => "_security_extraDataCollection_datum-30"
]
The content of a url input :
"block_prefixes" => array:4 [▼
0 => "form"
1 => "text"
2 => "url"
3 => "_security_extraDataCollection_datum-31"
]
And the content of a number input :
"block_prefixes" => array:3 [▼
0 => "form"
1 => "number"
2 => "_security_extraDataCollection_datum-33"
]
At first, I thought that was because I was using material-component-web, but even without CSS, this problem occur.
Any idea as to why url and number type are turned to text type when I render them from enbedded form?
Registration form
public function buildForm(FormBuilderInterface $builder, array $options) {
/** #var array $extraData */
$extraData=$options['extra_data'];
$builder->add('nom')
->add('prenom')
->add('email', EmailType::class)
->add('plainPassword', PasswordType::class, array(
'mapped'=>false,
'constraints'=>array(
new NotBlank(array(
'message'=>'Please enter a password',
)),
new Length(array(
'min'=>6,
'max'=>4096,
)),
),
));
if($extraData !== null && is_array($extraData) && count($extraData)) {
$builder->add('extraDataCollection', UnmappedMixedType::class, array(
'mapped'=>false,
'data'=>$extraData,
));
}
}
UnmappedMixedType form
public function buildForm(FormBuilderInterface $builder, array $options) {
/** #var array $extraData */
$extraData=$options['data'];
/** #var ExtraData $extraDatum */
foreach($extraData as $extraDatum) {
if($extraDatum->getType() == 'text') {
$builder->add('datum-'.$extraDatum->getId(), TextType::class, array(
'mapped'=>false,
'required'=>$extraDatum->getIsObligatoire(),
'label'=>$extraDatum->getLabel(),
));
} elseif($extraDatum->getType() == 'url') {
$builder->add('datum-'.$extraDatum->getId(), UrlType::class, array(
'mapped'=>false,
'required'=>$extraDatum->getIsObligatoire(),
'label'=>$extraDatum->getLabel(),
));
} elseif($extraDatum->getType() == 'number') {
$builder->add('datum-'.$extraDatum->getId(), NumberType::class, array(
'mapped'=>false,
'required'=>$extraDatum->getIsObligatoire(),
'label'=>$extraDatum->getLabel(),
));
} elseif($extraDatum->getType() == 'checkbox') {
$builder->add('datum-'.$extraDatum->getId(), CheckboxType::class, array(
'mapped'=>false,
'required'=>$extraDatum->getIsObligatoire(),
'label'=>$extraDatum->getLabel(),
));
} elseif($extraDatum->getType() == 'choice' && $extraDatum->getChoix() !== null && count($extraDatum->getChoix()) >= 1) {
$builder->add('datum-'.$extraDatum->getId(), ChoiceType::class, array(
'mapped'=>false,
'required'=>$extraDatum->getIsObligatoire(),
'label'=>$extraDatum->getLabel(),
'multiple'=>$extraDatum->getIsChoixMultipleUtilisateur(),
'choices'=>array_combine($extraDatum->getChoix(), $extraDatum->getChoix()),
));
}
}
}
Twig view
{% if form.extraDataForm is defined %}
<div class="app-auth-left-frame-extra">
<div class="app-form-container">
<div class="app-form_field-container">
{% for field in form.extraDataForm %}
{{ dump(field) }}
{% if field.vars.block_prefixes[1] == 'text' or field.vars.block_prefixes[1] == 'number' %}
<div class="mdc-text-field mdc-text-field--outlined">
{{ form_widget(field, {'attr': {'class': 'mdc-text-field__input'}}) }}
<div class="mdc-notched-outline">
<div class="mdc-notched-outline__leading"></div>
<div class="mdc-notched-outline__notch">
{{ form_label(field, null, {'label_attr': {'class': 'mdc-floating-label'}}) }}
</div>
<div class="mdc-notched-outline__trailing"></div>
</div>
</div>
{% elseif field.vars.block_prefixes[1] == 'checkbox' %}
<div class="mdc-form-field">
<div class="mdc-checkbox">
{{ form_widget(field, {'attr': {'class': 'mdc-checkbox__native-control'}}) }}
<div class="mdc-checkbox__background">
<!--suppress HtmlUnknownAttribute -->
<svg class="mdc-checkbox__checkmark" viewBox="0 0 24 24">
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59"></path>
</svg>
</div>
</div>
{{ form_label(field, null, {'label_attr': {'class': 'app-txt-light-emphasis'}}) }}
</div>
{% elseif field.vars.block_prefixes[1] == 'choice' %}
<div>{{ form_widget(field) }}</div>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endif %}
UrlType Field as the documentations says:
The UrlType field is a text field that prepends the submitted value with a given protocol (e.g. http://) if the submitted value doesn't already have a protocol.
If you would like an input with url type create your own Form Field Type like that:
class MyUrlType extends AbstractType {
/**
* {#inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['type'] = 'url';
}
/**
* {#inheritdoc}
*/
public function getParent()
{
return __NAMESPACE__.'\TextType';
}
}
From here https://symfony.com/doc/current/form/create_custom_field_type.html

Add classes and attributes to all multiple selects in Symfony2?

I want to customize all multiple selects of my application like that :
<select class="selectpicker show-tick" data-size="auto">
...
</select>
How should I do that?
EDIT for ncrocfer
This is my build form method:
This is not complete, lack some stuff...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('misc')
->add('url')
->add('attachment', 'file')
->add('time_estimated')
->add('started_at')
->add('finished_at')
->add('default')
->add('deadline')
->add('priority', 'entity', array(
'class' => 'LanCrmBundle:TaskPriority',
'property' => 'title',
'multiple' => false
))
->add('project', 'entity', array(
'class' => 'LanCrmBundle:Project',
'property' => 'title',
'multiple' => false
))
->add('category', 'entity', array(
'class' => 'LanCrmBundle:TaskCategory',
'property' => 'title',
'multiple' => false
))
->add('user', 'entity', array(
'class' => 'LanSecurityBundle:User',
'property' => 'username',
'multiple' => false
))
->add('products', 'entity', array(
'class' => 'LanCrmBundle:Product',
'property' => 'title',
'multiple' => true
))
;
}
Use the attr attribute in your form buider :
<?php
namespace Foo\BarBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class FooType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('foo', 'choice', array(
'choices' => array(0 => 'Option 1', 1 => 'Option 2'),
'attr' => array('class' => 'selectpicker show-tick', 'data-size' => 'auto'),
))
;
}
}
Edit
If you have a lot of forms like you said in your comment, you can use the form customization.
Create a new template file :
{# src/Foo/BarBundle/Resources/views/Form/fields.html.twig #}
{% block choice_widget_collapsed %}
{% spaceless %}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %} class="selectpicker show-tick" data-size="auto">
{% if empty_value is not none %}
<option value="">{{ empty_value|trans({}, translation_domain) }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('choice_widget_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('choice_widget_options') }}
</select>
{% endspaceless %}
{% endblock choice_widget_collapsed %}
Then import your template inside your application configuration :
# app/config/config.yml
twig:
form:
resources:
- 'FooBarBundle:Form:fields.html.twig'
The change will be effective on all your select.
Use attr attribute in FormBuilder:
'attr' => array('class'=>'selectpicker show-tick', 'data-size'=>'auto')

problems with request in a embed form

HEllo sorry but my english isnt good.
I'm developing an application in Symfony 2.3.6 where i have to save in a DB (postgres) the values from a user.
The problem happens when my embed form (pais + region) that has 2 submit buttons the user press the second button. The system throw
Child "salvar_region" does not exist.
The question is how can I detect if the second button is being pressed if the system is throwing an exception?
Here is my Default controller
public function addLocalAction(Request $request)
{
$region = new Region();
$localidad = new Pais();
$localidad->setRegion($region);
$form = $this->createForm(new localidadType(), $localidad);
if($request->isMethod('POST')){
$form->handleRequest($request);
$form->getData();
if ($form->get('salvarPais')-> isClicked()){
$objeto = new Pais();
$objeto->setNombrePais($form->get('nombrePais')->getData());
$em = $this->getDoctrine()->getManager();
$em->persist($objeto);
$em->flush();}
if ($form->get('salvarregion')->isClicked()){
$objeto = new Region();
$objeto->setNombreRegion($form->get('nombreRegion')->getData());
$objeto->setNombreRegion($form->get('numeroRegion')->getData());
$em = $this->getDoctrine()->getManager();
$em->persist($objeto);
$em->flush();}
return $this->redirect($this->generateUrl('localidades'));
}
return $this->render('plataformaPlataformaBundle:Default:localidades.html.twig', array('form'=> $form->createView()));
}
My html.twig
<form action="{{ path('localidades')}}" method="post" {{ form_enctype(form) }}>
<h3>Agregar País</h3>
<div class="pais">
{{ form_row(form.nombrePais) }}
{{ form_row(form.salvarPais) }}
</div>
<form action="{{ path('localidades')}}" method="post" {{ form_enctype(form) }}>
<h3>Agregar Region</h3>
<div class="region">
{{ form_start(form) }}
{{ form_errors(form)}}
{{ form_row(form.region.nombreRegion) }}
{{ form_row(form.region.numeroRegion) }}
{{ form_row(form.region.pais) }}
{{ form_row(form.region.salvarregion) }}
{{ form_end(form) }}
</div>
</form>
and my 2 type forms
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nombreRegion', 'text', array('label' => 'Nombre de Región: '));
$builder->add('numeroRegion', 'integer', array('label' => 'Número de Región: '));
$builder->add('pais', 'entity', array('label' => 'País al que pertenece: ',
'class' => 'plataformaPlataformaBundle:Pais',
'property' => 'nombrePais'));
$builder->add('salvarregion', 'submit', array('label' => 'Guardar Región'));
$builder->getForm();
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nombrePais', 'text');
$builder->add('salvarPais', 'submit', array('label' => 'Guardar País'));
$builder->add('region', new regionType());
$builder->getForm();
}
PD: A lot of thanks if someone can help me
PDx2: here is an example of the URL request:{"region":{"nombreRegion":"ewrew","numeroRegion":"4","pais":"3","salvarregion":""},"_token":"853d5460b076e01fdf4cef4c59c33e836ab64af3"}
The error you got doesn't look like the name you gave the button during the builder process.
Anyway, to tell if a specific submit was clicked you can use:
if($form->get('salvarregion')->isClicked()) {
}

Symfony2 Update Specific Field in Form Collection

I have an interesting problem. I couldn't find any solution in stackoverflow and also google. I have an Entity User and User have some metas. So I created a UserMeta Entity and also UserMetaValue. In user form there is lots of tabs. And I used these metas in the tabs. Some of them in first tabs, some of them in other tabs. And all tabs have their own form. When I bind a form on active tab, active tab metas update, others changed to NULL.
StudentPersonalType.php
namespace ATL\UserBundle\Form\Type;
use ATL\CommonBundle\Utils\Shortcut;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
class StudentPersonalType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options){
$builder->add("first_name", null, array(
"label" => "İsim",
"required" => true,
"attr" => array(
"class" => "span10"
)
))->add("last_name", null, array(
"label" => "Soyisim",
"required" => true,
"attr" => array(
"class" => "span10"
)
))->add("username", null, array(
"label" => "Öğrenci Numarası",
"required" => true,
"attr" => array(
"class" => "span10"
)
))->add("email", null, array(
"label" => "Email",
"required" => true,
"attr" => array(
"class" => "span10"
)
))->add('metas', 'collection', array(
'label' => "Metas",
'type' => new UserMetaType()
));
}
public function getName(){
return "personal";
}
public function setDefaultOptions(OptionsResolverInterface $resolver){
$resolver->setDefaults(array(
"data_class" => "ATL\UserBundle\Entity\User"
));
}
}
StudentEducationType.php
namespace ATL\UserBundle\Form\Type;
use ATL\CommonBundle\Utils\Shortcut;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
class StudentEducationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options){
$builder->add('metas', 'collection', array(
'label' => "Metas",
'type' => new UserMetaType(),
'by_reference' => false
));
}
public function getName(){
return "education";
}
public function setDefaultOptions(OptionsResolverInterface $resolver){
$resolver->setDefaults(array(
"data_class" => "ATL\UserBundle\Entity\User"
));
}
}
And twig
<div id="personal-info" class="tab-pane row-fluid active">
<form style="margin:20px 0 0 0;" class="ajaxForm form-horizontal form-row-seperated" action="{{ formAction }}">
{{ form_row(form.first_name) }}
{{ form_row(form.last_name) }}
{{ form_row(form.email) }}
{{ form_row(form.username) }}
{% for meta in form.metas %}
{% if meta.value.vars.label in formValues.personal %}
{{ form_widget(meta) }}
{% endif %}
{% endfor %}
{{ form_row(form._token) }}
<div class="form-actions" style="margin-bottom:0;">
<button class="btn blue" type="submit"><i class="icon-ok"></i> Kaydet</button>
</div>
</form>
</div>
<div id="education-info" class="tab-pane row-fluid">
<form style="margin:20px 0 0 0;" class="ajaxForm form-horizontal form-row-seperated" action="{{ formAction }}">
{% for meta in educationForm.metas %}
{% if meta.value.vars.label in formValues.education %}
{{ form_widget(meta) }}
{% endif %}
{% endfor %}
{{ form_row(educationForm._token) }}
<div class="form-actions" style="margin-bottom:0;">
<button class="btn blue" type="submit"><i class="icon-ok"></i> Kaydet</button>
</div>
</form>
</div>
I filter collection fields by check it in twig file with IF statement.
I ask my question again, How could I use metas in different form in same page without affecting the others?
You have done half the job of filtering out the irrelevant fields for rendering. But you also need to filter out the irrelevant fields for form binding.
When you bind the request to the form it is expecting values for every UserMeta entity because there is a field for all of them in the UserMetaType collection. You'll need to remove all the UserMetaType forms which don't correspond to one of your submitted values. It's probably best to this with a FormEvents::PRE_BIND listener.
You can see a simpler example of this at Form: Avoid setting null to non submitted field. It will be slightly more complex for you, because you'll have to iterate through the collection of UserMetaType forms and remove the ones which you don't want bound.

Form default values is not shown

The problem as it is. I'm trying to set defalut form values, and there's no way i can achieve this.
Page layout
{% extends bundle ~ "Bundle::reg.html.twig" %}
{% form_theme regForm 'AcmeBundle:Form:order_type_fields.html.twig' %}
{% block content %}
<form action="{{ path('reg') }}" {{ form_enctype(regForm) }} method="POST">
<div>
{{ form_widget( regForm.firstname )}}
</div>
{{ form_rest( regForm )}}
<input type="submit>
</form>
{% endblock %}
fields layout
{% block text_widget %}
{% spaceless %}
<label>{{label}}</label>
<input type="text" {{ block('widget_attributes') }} value="{{ value }}">
{% endspaceless %}
{% endblock text_widget %}
Controller
$user = new User();
$regForm = $this->get('form.factory')->create(new RegForm(), $user);
return $this->render("FrontendBundle:Order:type.html.twig", array(
'regForm' => $regForm->createView(),
);
Form
class RegForm extends AbstractType
{
public function buildForm( FormBuilder $builder, array $options ){
$builder->add( 'firstname', 'text', array( 'label' => ' ', 'data' => 'Enter your name here' ) );
}
public function getName()
{
return 'reg';
}
}
I've already tried to set default field data in many ways:
in my controller by defining firstname field (
$user->setFirstname('Enter your name here');
).
In form builder by using setData method (
$builder->add( 'firstname', 'text', array( 'label' => ' ' ) )->setData(array('firstname' => 'Enter your name here'));
Or just
$builder->setData(array('firstname' => 'Enter your name here'));
All other form stuff work's just fine. For example, i can set label 'FIRSTNAME' without any problems. So, what am i missing?
UPD: After first answer i decided to ask a direct question:
Why doesn't work default value for this, while label works just fine:
$builder->add('firstname', 'text', array('label' => 'name', 'data' => 'Andrew'));
?
Maybe some mistakes in twig templates?
Have you tried this in your Form Type:
$builder
->add('firstname','hidden', array(
'attr' => array(
'value' => 'Enter your name here',
),
))
It seems to me, though, that you want to use a placeholder (HTML5) instead:
$builder
->add('firstname','hidden', array(
'attr' => array(
'placeholder' => 'Enter your name here',
),
))
In your controller, set the data on the $user object before creating the form
$user = new User();
$user->setFirstname('Default name');
$regForm = $this->get('form.factory')->create(new RegForm(), $user);
BTW you might want to use the placeholder attribute on the input:
<input placeholder="Enter your name here">
You can do this by adding the 'attr' option on the form builder:
$builder->add('firstname', 'text', array(
'attr' => array('placeholder' => 'Enter your name here'),
));