Using TBBC Money/Currency Bundle for Symfony/Bootstrap Forms - php

I don't think this question has been raised looking at the history and on google...
I'm discovering symfony2 for a personal project and I'm not sure to take the problem the right way when it comes to implementing a form with TBBC Money/Currency bundle (found on packagist).
I have a "Expense" class containing a price field (type "Money") and for which I want to create a form.
In my "ExpenseType" file I have the following:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('title', TextType::class)
->add('actualDate', DateType::class, array('widget' => 'single_text'))
->add('comment', TextareaType::class)
->add('price', MoneyType::class, array())
->add('user', 'entity', array(
'class' => 'VPAccountsBundle:User',
'property' => 'username'))
;
}
On my twig file displaying the form I have:
<div class="row">
<div class="col-lg-3 col-md-3 control-label">
{{ form_label(form.price, "Amount" ) }}
</div>
<div class="col-lg-4 col-md-4">
{{ form_widget(form.price , { 'attr':{ 'class':'form-control', 'placeholder':'Amount' } } ) }}
</div>
{{ form_errors(form.price) }}
</div>
What I get is this.
What I would like to get is a bootstrap input with dropdown button (see mockup). but I really don't know how to proceed.
Has anyone faced this kind of situation? Any help would be appreciated! :)
Thanks a lot.

Theme a widget or form in Symfony is well documented here and IMO you should go through Inside the same Template as the Form. You could extends from form_div_layout.html.twig and then on your custom template overrides how money_widget is render by changing the following block:
{%- block money_widget -%}
{{ money_pattern|replace({ '{{ widget }}': block('form_widget_simple') })|raw }}
{%- endblock money_widget -%}
Hope it helps

Replying to myself...
As correctly indicated in the bundle documentation I had to configure my config.yml to declare the new type to twig:
# config.yml
twig:
form:
resources:
- 'TbbcMoneyBundle:Form:fields.html.twig'
The form elements are rendered much better and should be easily customizable.

Related

Customize collection using bootstrap

I have a collection of an embedded form.
I'd like to customize the embedded form.
I want that each entry of the embedded form to be in 1 line, something like that :
<div class="row">
<div class="col-sm-6">field1</div>
<div class="col-sm-6">field2</div>
</div>
But symfony's doc is, in my opinion, poor for this.
I have a form ApplicationType :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('responsables', 'collection', array(
'label' => ' ',
'type' => new ApplicationResponsablesType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' =>false
))
//...
And ApplicationResponsablesType :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('type', null, array(
'required' => true,
))
->add('id')
;
I really don't understand how to use {% block ___ %}.
my Application new.html.twig where I have the form :
{% block body -%}
<div class="container">
<br>
{{ form_start(form) }}
{# some other fields #}
{{ form_row(form.responsables) }}
{# some other fields #}
<div class="pull-right">
{{ form_row(form.submit) }}
</div>
{{ form_end(form) }}
{# ... closing block and tags... #}
I tried some things but since I didn't understand how it works and what I actually tried, I'll not put it...
Can anyone help me or lead me ? Thanks!
Edit :
As you can see on this image :
On the top there is the first part of Application's form.
And if the user add a lot of Responsable, this is huge. So I'd like to have Type and Uid on the same line.
(Here I'm talking only for responsable, but there is other collection on this form so that's why I'd like to simplify it)
Yes, Symfony doc is not very clear regarding this point.
To achieve what you want:
Create a file prototype_layout.html.twig:
{% block _application_responsables_entry_row %}
<div class="row">
<div class="col-sm-6">{{ form_row(form.type) }}</div>
<div class="col-sm-6">{{ form_row(form.id) }}</div>
</div>
{% endblock %}
The name of the block is important. The first part is _application because your parent form is called ApplicationType and the second part _responsables because your form field owning the collection is called so. The third part must always be _entry_row in order for this to work.
To make sure you got the first and second part of the name right, take a look in the DOM at the id of the select html element corresponding to your collection using the inspector tool of your browser.
Declare this file as a global form theme in the twig section of config.yml:
twig:
form_themes:
- 'AppBundle:Form:prototype_layout.html.twig' #adapt this path if you saved your file elsewhere
You can also use the file directly in your form view (in your case new.html.twig):
{% use "AppBundle:Form:prototype_layout.html.twig" %}
To bring those content in Inline, and as discussed in chat.
Here is one of the solution by using pure CSS.
Image reference for your required output:
As you have given the code in https://codeshare.io/GbQPkA , we can achieve the output by CSS.
Just add the below given CSS in your stylesheet, It may works fine.
CSS
div[id*="mybundle_application_responsables_"]{
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
div[id*="mybundle_application_responsables_"] > .form-group {
flex-grow: 1;
width: 100%;
padding: 10px;
}
Hope this may help you.If you prefer I will share the code in snippet with the updated CSS for demo.
Thanks.

Display custom message for checkbox (terms of service/privacy)

I am still new to Symfony and Php, so I am using the CheckboxType code from Symfony docs.
Currently no message is appearing if a user attempts to register and the checkbox is unchecked, but it will still prevent the user from making a account.
(1) I would like a error message to appear next to the checkbox in red stating the box must be checked in order to proceed. I would also like to customize this message.
Thank you!
Register.html
{% extends 'base.html.twig' %}
{% block body %}
<div class="container">
<div class="row">
<div class="col-xs-12">
<h1>Register!</h1>
{{ form_start(form) }}
{{ form_row(form.username) }}
{{ form_row(form.email) }}
{{ form_row(form.plainPassword.first, {
'label': 'Password'
}) }}
{{ form_row(form.plainPassword.second, {
'label': 'Repeat Password'
}) }}
Terms of service
{{ form_widget(form.termsAccepted) }}
cancel
<button type="submit" class="btn btn-primary" formnovalidate>
Register
</button>
<br></br>
<p>Privacy Policy
{{ form_end(form) }}
</div>
</div>
</div>
{% endblock %}
RegistrationForm.php
class UserRegistrationForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', EmailType::class)
->add('username', TextType::class)
->add('plainPassword', RepeatedType::class, ['type' => PasswordType::class])
->add('termsAccepted', CheckboxType::class, array(
'mapped' => false,
'constraints' => new IsTrue(),));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
'validation_groups' => ['Default', 'Registration']
]);
}
}
The problem is that you are using:
{{ form_widget(form.termsAccepted) }}
for rendering the checkbox. This will only render the widget, whereas:
{{ form_row(form.termsAccepted) }}
as is used by all the user fields would contain the label, the widget and the error message. If you want to keep the widget, e.g. because using form_row messes up the template somehow you could render the errors individually using:
{{ form_errors(form.termsAccepted) }}
You might also want to check out the documentation on Form Customization.

Symfony/TWIG: Unable to set custom theme for form with dynamic ID (createNamedBuilder)

I wanted to replace Symfony's default radio button widget with Bootstrap's Radio Button Group. I was trying to achieve that by setting a custom theme for an individual field in Symfony's form created with createNamedBuilder function. I failed, because custom field themes require the ID of the field which is dynamic in my case. I know that having variables in theme names is impossible in TWIG, but maybe there is an alternative approach that I could use to resolve my issue.
CODE
I have a Controller which creates multiple instances of one form type in a loop. The name of the form is dynamically created by concatenating requestform_ and the ID of the form:
public function listAction(Request $request)
{
$entityManager = $this->getDoctrine()->getManager();
$requestForms = $entityManager->getRepository('AppBundle:RequestForm')->findBy(array(), array('id' => 'ASC'));
$forms = array();
foreach ($requestForms as $requestForm) {
$formBuilder = $this->get('form.factory')->createNamedBuilder('requestform_'.$requestForm->getId(), RequestFormType::class, $requestForm);
$form = $formBuilder->getForm()->handleRequest($request);
$forms[] = $form->createView();
}
return $this->render('form/index.html.twig', array('forms' => $forms));
}
buildForm function of the RequestFormType prepares radio button widget and looks like this:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('status', EntityType::class, array(
'class' => 'AppBundle:Status',
'choice_label' => 'name',
'expanded' => true,
'multiple' => false
));
}
The Controller renders the following template:
{% block content %}
{% for form in forms %}
{{ form_start(form) }}
{{ form_widget(form.status) }}
{{ form_end(form) }}
{% endfor %}
{% endblock %}
Which is themed to show Bootstrap's button group selector instead of radio buttons:
{% block _requestform_1_status_widget %}
<div id={{ form.vars.id }} class="btn-group" data-toggle="buttons">
{% for status in form.children %}
<label for={{ status.vars.id }} class="btn btn-primary required custom-button-radio">
<input type="radio" id={{ status.vars.id }} name={{ status.vars.full_name }} required="required" value={{ status.vars.value }}>
{{ status.vars.label }}
</label>
{% endfor %}
</div>
{% endblock _requestform_1_status_widget %}
As you may have noticed this will work only for requestForm ID 1 and will not work for other ID values due to TWIG not allowing variables in block names, i.e. {% block _requestform_VARIABLE_status_widget %}.
Any help much appreciated! Thanks
My gut feeling is that you might want to have only one form that includes a CollectionType field with entry_type = RequestFormType::class, and then in the twig, apply a form to the "outer" form as a whole. You should still be able to manage things the way you wanted.

How to render same form multiple times in Symfony2?

I have a template with multiple carts. There can be a variable amount of carts, there's no fixed limit.
In each cart I want to have a form where the user can select a country. If he submits the form the shipping costs should be established.
Now I'm doing the following to achieve it in twig:
{% for cart in carts %}
{# Some template stuff #}
{{ form_start(form) }}
<div class="form-input">
<label for="country" class="middle-color">Country <span class="active-color">*</span></label>
{{ form_widget(form.country) }}
{{ form_end(form) }}
{% endfor %}
This is my form builder:
$form = $this->createFormBuilder()
->add('country', 'choice', array('choice_list' => $choiceList, 'label' => 'country',
'attr' => array('class' => "custom-selectbox dark-color light-gradient")))
->getForm();
Now the problem is that this logic works fine for the first cart, but there's no form displayed for further carts. How can I deal with this?
I came across this and another question about the similar issue. You can find my first answer for a solution here.
To wrap it up, I did not call the createView() function on the form in the controller, as usually done when passing the form to the view, but in the twig view itself.
E.g. in your controller action you do return the form object itself:
return $this->render('AppBundle:Cart:list.html.twig', ['formObject' => $form];
and in your view you would set the form in each loop:
{% for cart in carts %}
{# Some template stuff #}
{% set form = formObject.createView %}
{{ form_start(form) }}
<div class="form-input">
<label for="country" class="middle-color">Country <span class="active-color">*</span></label>
{{ form_widget(form.country) }}
{{ form_end(form) }}
{% endfor %}
You should use collection form type. Here is a guide to start with How to Embed a Collection of Forms
P.S. Notice that after rendering a form widget Form component marks it as rendered and does not render once more.

Symfony2 formbuilder - entity readonly field as label

Is there any possibility in symfony2 to display a readonly-field of an entity as a label rather than a text field or whatever?
I am currently using the following code, but using a disabled text field does not feel very sophisticated:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('readonlyfield', 'text', array('property_path' => 'readonlyfield.displayString','disabled' => true));
$builder->add('editablefield', 'textarea');
}
I am using symfony 2.4.4..
EDIT:
I am using this form type from within another form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('mySubEntities', 'collection', array('type' => new MySubEntryType()));
$builder->add('save_to_db', 'submit', array('label' => 'Submit'));
}
twig file:
{{ form_start(form) }}
{% for row in form.mySubEntities %}
<li>
<ul>
<table>
<tr><td>{{ form_label(row.readonlyfield) }} </td><td>{{ form_widget(row.readonlyfield) }}</td></tr>
<tr><td>{{ form_label(row.editablefield) }}</td><td> {{ form_widget(row.editablefield) }}</td></tr>
</table>
</ul>
</li>
{% endfor %}
{{ form_end(form) }}
You can access value in form using {{ form.vars.value.yourfield }}.
You have a nested/collection so use {{ row.vars.value.yourfield }}
Why don't you just render the entity property in your template instead of making it part of a form? You could make your own FieldType but that's not what I recommand. If you want the value to be displayed as a form like file I would use the readonly property.

Categories