2012-04-12 6 views
11

Nella mia applicazione, l'utente deve dare una data selezionando solo un mese e un anno in due elenchi a discesa. Come posso ottenerlo?Come visualizzare un menu a discesa di un anno in Symfony2

Ecco quello che ho provato finora:

nella mia forma:

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

che effettivamente funziona e lo visualizza esattamente come voglio, ma durante la convalida la forma, ottengo un errore:

This value is not valid 

Uno screenshot del risultato voluto:

Screenshot

+0

Attualmente, non esiste una soluzione semplice per il problema. A proposito, ho avuto lo stesso problema pochi giorni fa ma il mio è di circa minuti .. Ho inviato un [PR] (https://github.com/symfony/symfony/pull/3846) (non ancora unito), se vuoi , puoi aggiungere la tua funzione :) – egeloen

+0

Ciao, tre anni dopo, c'è una soluzione facile, qualcosa come '$ builder-> add ('mydate', 'date', array ('format' => 'SOLO ANNO ') '? – mario

risposta

8

Molto semplice, datetime richiede giorno!

È necessario il giorno di uscita, qualcosa di simile:

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

TWIG:

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

Questo è effettivamente quello che ho fatto, ma in Javascript –

+0

Ma ancora sf2 ha bisogno di conoscere il' giorno', quindi puoi fare solo un'opzione, e non usare nessun valore_valore, come nel mio esempio sopra –

+8

non funziona più a partire da Symfony 2.1 poiché il formato è controllato per la presenza dei simboli Y, M e D. Vedere https://github.com/symfony/symfony/issues/8345 – Cowlby

9

Esempio di carta di credito data di scadenza:

$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), 
)); 

Poi devi rendere questo campo manualmente.

modello ramoscello del vostro modulo:

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

Override date_pattern sarà nascondere giorno select. Riceverai il formato mese/anno.

4

@Oleg era abbastanza vicino alla risposta corretta. Devi utilizzare un trasformatore di visualizzazione per assicurarti che il DateTime diventi un giorno.

/* 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())); 
) 

Creare un trasformatore:

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; 
} 
} 

creare un modello ramoscello in cui si utilizza un tema modulo personalizzato dal file stesso:

{# 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) }} 

Riferimenti:

+1

+1 Ho dovuto definire il blocco date_widget in un altro modello, altrimenti affermava che la variabile "widget" non esisteva. – FoxException

4

ho a lavorare su un tipo di modulo personalizzato che consenta di risolvere tale problema. La soluzione è basata su ciò che @ oleg-andreyev ha proposto. La logica avvolta in un tipo di modulo.

Usage:

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

Il codice tipo di modulo:

<?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'; 
    } 
} 

È possibile copiare \ incollarlo o registrati fascio payum e utilizzare questo tipo da (sarà disponibile lì in prossima major release) .

0

Non sto utilizzando il menu a discesa, ma bootstrap-datetimepicker in single_text. Per me, salvare mese e anno in campi separati nel database sarebbe difficile, perché sto ordinando entro questa data. Così ho deciso di salvare sempre il primo giorno del mese scelto. Sto utilizzando DatetimepickerBundle e mia abitudine tipo di modulo sembra così:

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'; 
    } 
} 

E il risultato:

enter image description here

Problemi correlati