2012-10-18 13 views
6

Symfony2プロジェクトでは、埋め込みフォームを持つフォームには非常に複雑な構造があります....今、フォームの出力を特定の順序で表示する必要があります。Symfony 2 - フォームフィールドを並べ替える

ここに問題があります:私たちはform_widget(フォーム)を使用しています。そして、フォームの最後に特定のフィールドを移動するために、オブジェクト内の解決策(例:アノテーション)またはフォームビルダーを探しています。 symfony 1.4で、それは、ウィジェット-movefield()関数であった、私は...

Thxを推測...

答えて

3

フィールドを "並べ替え" する必要はありません。フィールドごとにform_labelおよび/またはform_widgetに電話するだけです。あなたは可能性Twig使うと仮定すると、例えば、実行します。

<div>{{ form_label(form.firstName) }}</div> 
<div>{{ form_widget(form.firstName) }}</div> 

<div>{{ form_label(form.lastName) }}</div> 
<div>{{ form_widget(form.lastName) }}</div> 
+0

ありがとうございますが、それはできません。私たちは非常に複雑な構造を持ち、form_widget(form)関数が必要なので、バックエンドでこれを行う必要があります! – snirgel

+0

フィールドを 'FormBuilder'インスタンスに希望の順序で追加しようとしましたか? –

+0

それはできません。私たちはディペンデンス、継承などで約80個のオブジェクト型をラウンドしていますので、手作業でそのようなものを操作することはできません.... – snirgel

0

を私は理解して、あなたは、最終的なテンプレートでのみform_widget(フォーム)を使用します。

あなたがformBをレンダリングする場合は、A、B、Cの順番を取得します

class ModelA { 
    private $A; 
    private $B; 

    // Getters and setters 
} 

class ModelB extends ModelA { 
    private $C; 

    // Getters and setters 
} 

/** 
* @DI\Service(id = "form.type.modelA") 
* @DI\Tag("form.type", attributes={ "alias":"model_a_type" }) 
*/ 
class FormAType extends AbstractType { 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
    $builder 
     ->add('A') 
     ->add('B') 
    ; 
    } 

    // getName and so on 
} 

/** 
* @DI\Service(id = "form.type.modelA") 
* @DI\Tag("form.type", attributes={ "alias":"model_b_type" }) 
*/ 
class FormAType extends AbstractType { 
    public function getParent() { 
    return "model_a_type"; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
    $builder 
     ->add('C') 
    ; 
    } 

    // getName and so on 
} 

我々は(ModelAType、ModelBType)彼らのために2つの継承したモデル(MODELA、ModelB)とフォームの種類を持っていると仮定しましょう、しかし、あなたA、C、Bが欲しい。 これを達成するには、フォームテンプレートを作成し、アプリへの参照を追加します。設定ファイル:

ここで、formBをレンダリングすると、希望の順序とコードの構造が表示されます。 これは、すべてのウィジェットが1回しかレンダリングされないために発生します。親ブロックを呼び出す前にレンダリングすると、ウィジェットの順序が変更されます。

9

あなたはこのバンドルを使用してフィールドを注文し直すことができます:https://github.com/egeloen/IvoryOrderedFormBundle

これは、あなたがこのようなことを行うことができます:

$builder 
->add('g', 'text', array('position' => 'last')) 
->add('a', 'text', array('position' => 'first')) 
->add('c', 'text') 
->add('f', 'text') 
->add('e', 'text', array('position' => array('before' => 'f'))) 
->add('d', 'text', array('position' => array('after' => 'c'))) 
->add('b', 'text', array('position' => 'first')); 

これはコアになる予定だったが、拒否され、引き出されました束にする。

3

今日のフォーム要素の注文で同じ問題が発生しました。 finishViewメソッドをオーバーライドして、FormViewコントロールの子プロパティに項目を並べ替えます特色になってしまった

trait OrderedTrait 
{ 
    abstract function getFieldsOrder(); 

    public function finishView(FormView $view, FormInterface $form, array $options) 
    { 
     /** @var FormView[] $fields */ 
     $fields = []; 
     foreach ($this->getFieldsOrder() as $field) { 
      if ($view->offsetExists($field)) { 
       $fields[$field] = $view->offsetGet($field); 
       $view->offsetUnset($field); 
      } 
     } 

     $view->children = $fields + $view->children; 

     parent::finishView($view, $form, $options); 
    } 
} 

は次にタイプでgetFieldsOrderメソッドを実装:

use OrderedTrait; 

function getFieldsOrder() 
{ 
    return [ 
     'first', 
     'second', 
     'next', 
     'etc.', 
    ]; 
} 
+1

これは、きれいで清潔な解決策です!ありがとう! – virtualize

+0

getFieldsOrderによって返されたフィールドリストに重みを追加するために、このコードを簡単に拡張することができます。もし誰かがこれを必要とするなら、私に連絡することができます。 –

3

をここにありますソリューション私は思い付いた。

私のタイプが拡張するクラスを作成しました。

namespace WF\CORE\CoreBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class WfBaseForm extends AbstractType 
{ 

    protected function useFields(FormBuilderInterface $builder, $fields) 
    { 
     foreach ($builder->all() as $field) { 

      if (!in_array($field->getName(), $fields)) 
       $builder->remove($field->getName()); 
     } 
    } 


    public function reorder(FormBuilderInterface $builder, $keys = array()) 
    { 
     $fields   = $builder->all(); 
     $ordered_fields = array_merge(array_flip($keys), $fields); 
     $this->useFields($builder, array()); 

     foreach($ordered_fields as $field) 
      $builder->add($field); 

    } 

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

次に、継承したクラスで使用できます。

class AddressType extends WfBaseForm 
{ 
public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     // I add as many fields as I need 
     $builder->add('…'); 
} 

このクラスを使用すると、テンプレートをレンダリングする前に、あなたは右のあなたのコントローラでそれを行うことができます

class ModifyAddressType extends BaseType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     parent::buildForm($builder, $options); 

     $builder->add('title', 'text', array('constraints' => array(new NotBlank()))); 

     $this->reorder($builder, array('title', 'firstname', 'lastname')); 
    } 
} 
0

上記のいずれかを拡張します。

$form = ... 

$view = $form->createView(); 

// Perform standard array operations to reorder: `$view->children` 
// Here's a very simple example: 

$firstField = $view->children['firstField']; 
unset($view->children['firstField']); 
$view->children['firstField'] = $firstField; 

return array('form' => $view); 

uasortしかしusortはA作成し、同様に動作します後でフォームレンダリングを中断する非連想配列。

0
{{ form_start(form) }} 

    <div>{{ form_label(form.title) }}</div> 
    <div>{{ form_widget(form.title,{'id': 'blog_title'})}}</div> 

    <div>{{ form_label(form.tag) }}</div> 
    <div>{{ form_widget(form.tag,{'id': 'blog_tag'})}}</div> 

    <div>{{ form_label(form.category) }}</div> 
    <div>{{ form_widget(form.category,{'id': 'blog_category'})}}</div> 

    <div>{{ form_label(form.image) }}</div> 
    <div>{{ form_widget(form.image,{'id': 'blog_image'})}}</div> 

    <div>{{ form_label(form.body) }}</div> 
    <div>{{ form_widget(form.body,{'id': 'editor'})}}</div> 

    <input type="submit" class="btn btn-success" value="Create" /> 
{{ form_end(form) }} 
関連する問題