【问题标题】:How to display a month-year dropdown in Symfony2如何在 Symfony2 中显示月份-年份下拉列表
【发布时间】:2012-04-12 14:21:06
【问题描述】:

在我的应用程序中,用户只需在两个下拉列表中选择月份和年份即可给出日期。我怎样才能做到这一点?

这是我迄今为止尝试过的:

在我的表格中:

$builder->add('date1', 'date', array(
 'widget'      => 'choice',
 'empty_value' => '',
 'format'      => 'MMMM-yyyy',
 'input'       => 'datetime',
 'years'       => range(date('Y'), date('Y') - 30, -1)
)

它实际上可以正常工作并完全按照我的意愿显示,但是在验证表单时,我收到一个错误:

This value is not valid

想要的结果截图:

【问题讨论】:

  • 目前,您的问题没有简单的解决方案。顺便说一句,几天前我遇到了同样的问题,但我的问题大约是几分钟。我已经提交了一个PR(尚未合并),如果你愿意,你可以添加你的功能:)
  • 嗨,三年后,有没有简单的解决方案,比如$builder->add('mydate', 'date', array( 'format'=> 'ONLY YEAR')

标签: forms symfony


【解决方案1】:

信用卡有效期示例:

$builder->add('expirationDate', 'date', array(
 'label' => 'Expiration date',
 'widget' => 'choice',
 'empty_value' => array('year' => 'Year', 'month' => 'Month', 'day' => 'Day'),
 'format' => 'dd-MM-yyyy',
 'input' => 'string',
 'data' => date('Y-m-d'),
 'years' => range(date('Y'), date('Y') + 10),
));

那么你必须手动渲染这个字段。

表单的树枝模板:

{{ form_row(form.expirationDate, {'date_pattern': '<span style="display: none;">{{ day }}</span> {{ month }} <span class="delim">&#47;</span> {{ year }}'}) }}

覆盖date_pattern 将隐藏日期选择。您将获得月/年格式。

【讨论】:

    【解决方案2】:

    很简单,datetime 需要一天!

    你需要输出一天,像这样:

            ->add(
                'ccExpirationDate',
                'date',
                array(
                    'format'          => 'MMM-yyyy',
                    'years'           => range(date('Y'), date('Y')+12),
                    'days'            => array(1),
                    'empty_value'     => array('year' => '----', 'month' => '----', 'day' => false)
                )
            )
    

    树枝:

    {{ 
        form_widget(
            form.payment.ccExpirationDate.day, 
            { 
                'attr': { 'style': 'display:none' } }
            ) 
    }}
    

    【讨论】:

    • 这确实是我在 Javascript 中所做的。
    • 但是 sf2 仍然需要知道 day,所以你可以只做一个选项,并且不使用 empty_value,就像我上面的例子一样
    • 这不再适用于 Symfony 2.1,因为检查格式是否存在 Y、M 和 D 符号。见github.com/symfony/symfony/issues/8345
    【解决方案3】:

    @Oleg 非常接近正确答案。您必须使用视图转换器来确保 DateTime 得到一天。

    /* In your formType.php */
    
    $builder->add(
       $builder->create('date1', 'date', array(
           'format'      => 'MMMM-yyyyd', // you need to have 'y', 'M' and 'd' here
           'years'       => range(date('Y'), date('Y') - 30, -1)
       ))
       ->addViewTransformer(new IncompleteDateTransformer()));
    )
    

    创建一个转换器:

    class IncompleteDateTransformer implements DataTransformerInterface
    {
    /**
     * Do nothing when transforming from norm -> view
     */
    public function transform($object)
    {
        return $object;
    }
    
    /**
     * If some components of the date is missing we'll add those. 
     * This reverse transform will work when month and/or day is missing
     *
     */
    public function reverseTransform($date)
    {
        if (!is_array($date)) {
            return $date;
        }
    
        if (empty($date['year'])) {
            return $date;
        }
    
        if (empty($date['day'])) {
            $date['day']=1;
        }
    
        if (empty($date['month'])) {
            $date['month']=1;
        }
    
        return $date;
    }
    } 
    

    创建一个树枝模板,您可以在其中使用来自文件本身的自定义表单主题:

    {# example.html.twig #}
    {% form_theme form _self %}
    
    {% block date_widget %}
    {% spaceless %}
        {% if widget == 'single_text' %}
            {{ block('field_widget') }}
        {% else %}
            <div {{ block('widget_container_attributes') }}>
                <div class="datetime_widget">
                    {{ date_pattern|replace({
                    '{{ year }}': form_widget(form.year),
                    '{{ month }}': form_widget(form.month),
                    '{{ day }}':  '',
                    })|raw }}
                </div>
            </div>
        {% endif %}
    {% endspaceless %}
    {% endblock date_widget %}
    
    <h2>Select a date</h2>
    {{ form(form) }}
    

    参考文献:

    【讨论】:

    • +1 我必须在另一个模板中定义 date_widget 块,否则它声称“widget”变量不存在。
    • 金色,仍然适用于 SF5。我必须创建一个新的表单类型并在其中弹出addViewTransformer(),否则整个表单正在被转换,不知何故不起作用。使用在主窗体中引用的YearOnlyChoiceType.php,一切都按照您的概述进行!
    【解决方案4】:

    我正在研究一种可以解决此类问题的自定义表单类型。该解决方案基于@oleg-andreyev 提出的建议。包装到表单类型的逻辑。

    用法:

    <?php
    $builder->add('exp_date', 'payum_credit_card_expiration_date');
    

    表单类型代码:

    <?php
    namespace Payum\Bundle\PayumBundle\Form\Type;
    
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\Form\FormView;
    use Symfony\Component\OptionsResolver\OptionsResolverInterface;
    
    class CreditCardExpirationDateType extends AbstractType
    {
        public function finishView(FormView $view, FormInterface $form, array $options)
        {
            if ('choice' == $options['widget']) {
                if (empty($view['day']->vars['value'])) {
                    $view['day']->vars['value'] = $view['day']->vars['choices'][0]->value;
                }
    
                $style = 'display:none';
                if (false == empty($view['day']->vars['attr']['style'])) {
                    $style = $view['day']->vars['attr']['style'].'; '.$style;
                }
    
                $view['day']->vars['attr']['style'] = $style;
            }
        }
    
        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->replaceDefaults(array(
                'years' => range(date('Y'), date('Y') + 9)
            ));
        }
    
        public function getParent()
        {
            return 'date';
        }
    
        public function getName()
        {
            return 'payum_credit_card_expiration_date';
        }
    }
    

    您可以复制\粘贴它或注册 payum 捆绑包并使用此类型(将在下一个主要版本中提供)。

    【讨论】:

      【解决方案5】:

      我没有使用下拉菜单,而是在single_text 中使用bootstrap-datetimepicker。对我来说,将月份和年份保存在数据库的不同字段中会很困难,因为我是在这个日期之前订购的。所以我决定总是保存所选月份的第一天。我正在使用DatetimepickerBundle,我的自定义表单类型如下所示:

      class MonthPickerType extends AbstractType
      {
          public function configureOptions(OptionsResolver $resolver)
          {
              $resolver->setDefaults(array(
                  'pickerOptions' => array(
                      'autoclose' => true,
                      'format' => 'mm/yyyy',
                      'startView' => 'year',
                      'minView' => 'year',
                  )
              ));
          }
      
          public function getParent()
          {
              return 'collot_datetime';
          }
      
          public function getName()
          {
              return 'month_picker';
          }
      }
      

      结果:

      【讨论】:

        猜你喜欢
        • 2021-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多