私たちの Symfony2 プロジェクトでは、フォームが埋め込まれたフォームの非常に複雑な構造を持っています.. これで、フォームの出力を特定の順序で行うという要件が得られました。
ここに問題があります: form_widget(form) を使用し、特定のフィールドをフォームの最後に移動するために、オブジェクト (注釈などを介して) またはフォームビルダーで解決策を探しています。symfony 1.4 では、widget-movefield() 関数だったと思います...
どうも...
私たちの Symfony2 プロジェクトでは、フォームが埋め込まれたフォームの非常に複雑な構造を持っています.. これで、フォームの出力を特定の順序で行うという要件が得られました。
ここに問題があります: form_widget(form) を使用し、特定のフィールドをフォームの最後に移動するために、オブジェクト (注釈などを介して) またはフォームビルダーで解決策を探しています。symfony 1.4 では、widget-movefield() 関数だったと思います...
どうも...
このバンドルを使用してフィールドを並べ替えることができます: 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'));
これはコアになる予定でしたが、却下され、バンドルにまとめられました。
今日、フォーム要素の順序付けで同じ問題が発生しました。
最終的には、finishView メソッドをオーバーライドし、FormView の children プロパティの項目を並べ替える特性になりました。
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.',
];
}
フィールドを「並べ替える」必要はありません。あなたがする必要があるのは、個別に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>
私が理解しているように、最終的なテンプレートでは form_widget(form) のみを使用したいと考えています。
2 つの継承されたモデル (ModelA、ModelB) とそれらのフォーム タイプ (ModelAType、ModelBType) があるとします。
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
}
formB をレンダリングすると、A、B、C の順序になりますが、A、C、B が必要です。これを行うには、フォーム テンプレートを作成し、アプリへの参照を追加します。設定ファイル:
#app/config/config.yml
twig:
....
form:
resources:
- YourAppBundle:Form:fields.html.twig
{# src/YourAppBundle/Resources/views/Form/fields.html.twig #}
{% block model_a_type_widget %}
{{ form_widget(form.A) }}
{{ form_widget(form.B) }}
{% endblock model_a_type_widget %}
{% block model_b_type_widget %}
{{ form_widget(form.A) }}
{{ form_widget(form.C) }}
{{ block('model_a_type_widget') }}
{% endblock model_b_type_widget %}
ここで、formB をレンダリングすると、目的の順序が表示され、コードの構造が維持されます。これは、すべてのウィジェットが一度だけレンダリングされるために発生するため、親ブロックを呼び出す前にレンダリングすると、それらの順序が変更されます。