2012-06-06 108 views

回答

39

解決方法很簡單,如果你希望你的自定義選項可用也嫩枝模板,必須在buildView()方法使用 $builder->setAttribute()buildForm方法 和 $view->set()方法了。

<?php 

namespace Acme\DemoBundle\Form\Type; 

use Symfony\Component\Form\AbstractType as FormAbstractType; 
use Symfony\Component\Form\FormBuilder; 
use Symfony\Component\Form\FormView; 
use Symfony\Component\Form\FormInterface; 

// For Symfony 2.1 and higher: 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

/** 
* ImagePreviewType 
* 
*/ 
class ImagePreviewType extends FormAbstractType 
{ 

    /** 
    * {@inheritDoc} 
    * For Symfony 2.0 
    */ 
    //public function getDefaultOptions(array $options) 
    //{ 
    // $options = parent::getDefaultOptions($options); 
    // $options['base_path'] = 'path/to/default/dir/'; 
    // 
    // return $options; 
    //} 

    /** 
    * {@inheritDoc} 
    * For Symfony 2.1 and higher 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'base_path'   => '', 
     )); 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     // For Symfony 2.0: 
     // $view->set('base_path', $form->getAttribute('base_path')); 

     // For Symfony 2.1 and higher: 
     $view->vars['base_path'] = $options['base_path']; 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    public function buildForm(FormBuilder $builder, array $options) 
    { 
     $builder 
      ->setAttribute('base_path', $options['base_path']) 
     ; 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    public function getName() 
    { 
     return 'image_preview'; 
    } 

    public function getParent(array $options) 
    { 
     // for Symfony 2.0: 
     // return 'field'; 

     // for Symfony 2.1 and higher: 
     return 'form'; 
    } 
} 

模板自定義表單類型(文件...阿克米/ DemoBundle /資源/視圖/表格/ fields.html.twig):

{% block image_preview_widget %} 
{% spaceless %} 
<img src="{{ base_path ~ value }}" alt="" {{ block('widget_container_attributes') }} /> 
{% endspaceless %} 
{% endblock %} 

註冊您的模板在應用自定義表單類型/配置/配置。陽明海運

twig: 
    debug:   %kernel.debug% 
    strict_variables: %kernel.debug% 
    form: 
     resources: 
      - 'AcmeDemoAdminBundle:Form:fields.html.twig' 

用法:用戶的圖像顯示預覽編輯時他的個人資料:

// src/Acme/DemoBundle/Form/Type/UserType.php 
namespace Acme\DemoBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilder; 

class UserType extends AbstractType 
{ 
    public function buildForm(FormBuilder $builder, array $options) 
    { 
     $builder->add('user_profile_image_file_name', new ImagePreviewType(), array(
      'base_path' => 'some/other/dir', 
     )); 
    } 
} 

2014年8月18日:更新了Symfony的2.1或更高

+0

我錯過了使用buildView傳遞給Twig的選項!謝謝! – ROLO

+0

如果我想爲所有表單類型(包括默認表單類型)添加一個選項,該怎麼辦?有沒有簡單的方法來做到這一點? – smarques

+0

[Form Type Extension](http://symfony.com/doc/current/cookbook/form/create_form_type_extension.html)是可能的。 – pulzarraider

2

我試過使用該選項array沒有成功,因爲它似乎只能攜帶小的預定義的子集。無論如何,這是我無法接受的...

但是,您可以通過表單__construct方法傳遞所有選項,並將其存儲在類屬性中供以後使用。然後,從buildForm您可以使用$this->"propertyName"訪問它...

它是由你來決定你是否想通過單一array或只是幾個變量到__construct ...

這只是一個粗略的例子:

class Foobar{ 
    private $update = false; 

    public function __construct($update = false){ 
     $this->update = $update; 
    } 


    public function buildForm(FormBuilder builder, array options){ 
     if ($update){ 
      // something 
     }else{ 
      // well, this is not an update - do something else 
     } 
    } 
} 
18

UPDATE:請注意,此解決方案僅適用於Symfony的2.0.x版本,這是過時的,使用setDefaultOptions代替getDefaultOptions


剛好,Symfony 2表單類型接受您可以在表單類型內使用的任何選項。您需要覆蓋getDefaultOptions方法來指定您的類型選項。

例如,我有一個類型MyCustomType接受my_option,此選項的false默認值時,MyCustomType實現可以是這樣的。

class MyCustomType extends AbstractType 
{ 
    public function buildForm(FormBuilder $builder, array $options) 
    { 
     if($options['my_option']){ 
      //do something 
     } else { 
      //do another thing 
     } 
     ... 
    } 

    public function getDefaultOptions(array $options) 
    { 
     return array(
      'my_option' => false 
     ); 
    } 

    public function getName() 
    { 
     return 'mycustomtype'; 
    } 
} 

稍後,您將需要在創建控制器的形式指定選項,使用buildForm第三個參數:

$form = $this->buildForm(new MyCustomType(), null, array(
    'my_option' => true 
)); 

如果未指定my_option選項,它採用默認值(false)。

+0

我在問這裏之前試過這個......但是,正如@jperovic所說,它只支持一小組預定義的鍵在選項數組中......我還沒有嘗試過他的解決方案......但我只是做它......無論如何感謝! – Throoze

+4

此解決方案支持您要使用的任何鍵,您只需重寫'getDefaultOptions'方法即可。 – eagleoneraptor

+0

也許這個答案不適合問題的作者,但它對我確實有用。因此,+1。 :) – Sasa

9

使用symfony的2.8,我通過使用擴展configureOptions()方法的建議解決方案成功。

class ElementType extends AbstractType 
{ 
    // ... 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'my_custom_option_parameter' => null, 
     )); 
    } 
} 

我需要使用ElementType作爲集合和嵌入表單。我意識到不可能將my_custom_option_parameter傳遞給CollectionType,因爲我沒有自定義的CollectionType,而是我的ElementType。如果您需要將my_custom_option_parameter通過CollectionType,則可以通過定義中的my_custom_option_parameter(請參閱文檔CollectionType FieldCollectionType數組來獲得成功。

實施例通過my_custom_option_parameter通過CollectionType

class OuterFormType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     //... 
     $builder->add('elements', CollectionType::class, array(
      'entry_type' => ElementType::class, 
      // ... 
      'entry_options' => array(
       'my_custom_option_parameter' => 'value is now set!' 
      ) 
     )); 
     //... 
    } 
} 
1

使用Symfony的3,我能夠通過設置在注入到我的形式類型的類configureOptions方法OptionsResolver默認選項傳遞自定義選項的形式:

在Controller:

//Compile whatever your options are here. Assume an array is returned 
$customOptions = $this->getMyCustomOptions($args); 
//Build the form: 
$form = $this->createForm(MyCustomFormType::class, array('my_custom_options' => $customOptions)); 

MyCustomFormType.php:

public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver->setDefaults([ 
     'data_class' => DataModel::class, 
     'my_custom_options' => [] 
    ]); 
} 
//custom options is now set in "$options" array: 
public function buildForm(FormBuilderInterface $builder, array $options) { 
    $builder->add('my_custom_fields', Type\ChoiceType::class, [ 
     'choices' => $options['my_custom_options'], 
     'mapped' => false //if not part of the data model. 
     . . . 

因此,它看起來像你可以定義與你的表單和數據提供商的合同來設置表單上的任意數據。

我剛剛成功實施了這個程序。請注意,在回程中,由於您在formBuilder中設置了'mapped' => false,,因此$form->getData()將不會返回選擇。要獲得選定的值:

$mySelectedValue = $form->get('my_custom_options')->getViewData(); 

在您的控制器中。爲什麼這是超越我的。 。 。

2

基礎上@pulzarraider答案我創建的代碼與變化爲symfony1.2 3.

您需要更改

OptionsResolverInterfaceOptionsResolver

FormBuilderFormBuilderInterface

在我的情況:

namespace MediaBundle\Form; 

use Symfony\Component\Form\AbstractType as FormAbstractType; 
use Symfony\Component\OptionsResolver\OptionsResolver; 
use Symfony\Component\Form\FormView; 
use Symfony\Component\Form\FormInterface; 
use Symfony\Component\Form\Extension\Core\Type\TextareaType; 
use Symfony\Component\Form\FormBuilderInterface; 

class ImageType extends FormAbstractType { 

    public function configureOptions(OptionsResolver $resolver) { 
     $resolver->setDefaults(array(
      'max_images' => '' 
     )); 
    } 

    public function buildView(FormView $view, FormInterface $form, array $options) { 

     $view->vars['max_images'] = $options['max_images']; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) { 

     $builder 
       ->setAttribute('max_images', $options['max_images']) 
     ; 
    } 

    public function getName() { 
     return 'image_preview'; 
    } 

    public function getParent() { 
     return TextareaType::class; 
    } 
} 
相關問題