Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override Symfony form MoneyType input as type="number"?

The Symfony MoneyType Field renders as input type="text" which allows a user to type whatever they want into the field.

How can I override this to render as input type="number" so that users can only enter numeric characters?

$formBuilder->add("amount", MoneyType::class, [
  'currency' => 'USD'
]);

Current output:

<div><label for="form_amount" class="required">Amount</label>$ <input type="text" id="form_amount" name="form[amount]" required="required"  /></div>

What I am trying to achieve:

<div><label for="form_amount" class="required">Amount</label>$ <input type="number" id="form_amount" name="form[amount]" required="required"  /></div>

I tried to simply override the attribute type, but all this did was add a second type attribute at the end, which didn't work because it's obviously invalid HTML.

$formBuilder->add("amount", MoneyType::class, [
  'attr' => [
    'type' => 'number',
  ],
  'currency' => 'USD'
]);

Here's my simple twig:

{{ form_start(form) }}

    {{ form_widget(form) }}

    <input type="submit" />

{{ form_end(form) }}

I'm also curious, why is this the default input type for Money? I'm considering extending or modifying the class to accommodate this, but I'm sure there's some advantage I'm not seeing.

like image 823
Jeff Puckett Avatar asked Jul 04 '16 19:07

Jeff Puckett


Video Answer


2 Answers

Why not use 'scale' to specify the number of decimal places, and also use 'placeholder' to tell the user the format:

->add('amount', MoneyType::class, array(
        'label' => 'Enter Amount:',
        'scale' => 2,
        'attr' => array(
                'placeholder' => 'x.xx',
        ),
))

I'm not sure if this is helpful or not.

Edit #2. After getting feedback, i think this should work for you:

use Symfony\Component\Validator\Constraints\Regex;
...

->add('amount', MoneyType::class, array(
        'label' => 'Enter Amount:',
        'scale' => 2,
        'attr' => array(
                'placeholder' => 'x.xx',
        ),
        'constraints' => array(
                new Regex( array( 'pattern' => '/[0-9]{1,}\.[0-9]{2}/')),
        ),
))

See this link for info on adding Validation: http://symfony.com/doc/current/book/forms.html#adding-validation

The above regular expression specifies at least 1 proceeding digit before the decimal, and 2 digits following the decimal place. In your original post you referred to 'currency', but that is a 'string'. You can modify the regular expression based on your needs.

I haven't verified this (I use something similar), but I think it should work.

like image 197
Alvin Bunk Avatar answered Nov 11 '22 19:11

Alvin Bunk


You can customise how the MoneyType is rendered.

{% extends 'form_div_layout.html.twig' %}

{% block money_widget %}
    {%- set type = type|default('number') -%}
    {{ parent() }}
{% endblock %}

Sources:

http://symfony.com/doc/current/form/form_customization.html#method-2-inside-a-separate-template https://github.com/symfony/symfony/issues/22937#issuecomment-304609466

like image 29
Nicodemuz Avatar answered Nov 11 '22 20:11

Nicodemuz