-->

Symfony 2: How to render date field without a day?

2019-06-27 04:28发布

问题:

I'm trying to build form with date field, where user can pick a month and year only (without day of month), but i can't figure out how to achieve this.

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add(
        'month',
        'date',
        array(
            'label' => 'Month & year',
            'input' => 'array',
            'widget' => 'choice',
        ));

    $builder->add('submit',
                  'submit');
}

Ideal result is two dropdown lists: list of months (number representation) and list of years (4 digit, 5 last years).

I think i can use 2 choice type fields but maybe there is a more elegant solution?

回答1:

You can do something like this in your twig file.

    {{ form_widget(yourForm.month.month) }}
    {{ form_widget(yourForm.month.year) }}

This will display two choice fields, one for month and one for year. I suggest change field name from month to something else. I'm not sure but it may conflict. I hope this helps..!

EDIT: To show the last 5 years, in your Form builder,

   $builder->add(
     'month',
     'date',
     array(
        'years' => range(date('Y'), date('Y')-5)
        'label' => 'Month & year',
        'input' => 'array',
        'widget' => 'choice',
     ));


回答2:

I think you can do something which will be nicer for your users but more complicated for you.

You can use the Bootstrap Datetimepicker (http://www.malot.fr/bootstrap-datetimepicker/) and set it up in a way that the user can select only year and month like in this picture:

When you call the script, set the format as "mm-yyyy" or something like this.

<script>
        $(function (){
            $(".datepicker").datetimepicker({
                weekStart: 1,
                format : 'mm-yyyy'
            });
        });
</script>

The details of this solution must be further investigated, but this is the general idea.



回答3:

You shouldo go semantic and use a "month" type input. Then, of course, you can fallback to any javascript datepicker when client is not supporting such input type. Here is a super-simple (but fully working) code example (for Symfony 2.8 or higher):

<?php

namespace AppBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;

/**
 * Month Type.
 */
class MonthType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->addModelTransformer(new CallbackTransformer(
                function ($dateTime) {
                    return empty($dateTime) ? null : $dateTime->format('Y-m');
                },
                function ($monthString) {
                    return new \DateTime("$monthString-01");
                }
            ))
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['type'] = 'month';
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return TextType::class;
    }
}


回答4:

Possibly the easiest way you can achieve this if you dont mind the day being submitted is just hide the day input with a class:

{{ form_start(form) }}
{{ form_widget(form.date.day, {'attr': {'class': 'hide'}}) }}
{{ form_widget(form) }}
{{ form_end(form) }}