2012-10-18 35 views
6

Trong dự án Symfony2 của chúng tôi, chúng tôi có cấu trúc rất phức tạp cho các biểu mẫu với các biểu mẫu nhúng .... Bây giờ chúng tôi có yêu cầu đưa đầu ra của biểu mẫu theo một thứ tự cụ thể. Và đây là vấn đề: Chúng tôi sử dụng form_widget (form) và bây giờ chúng tôi đang tìm kiếm một giải pháp trong đối tượng (ví dụ: thông qua chú thích) hoặc formbuilder để di chuyển một trường cụ thể đến cuối biểu mẫu. trong symfony 1.4 đó là widget movefield() chức năng, tôi đoán ...Symfony 2 - sắp xếp lại các trường biểu mẫu

Thx ...

Trả lời

3

Không cần để "sắp xếp lại" lĩnh vực. Tất cả những gì bạn cần làm là gọi form_label và/hoặc form_widget cho từng trường riêng lẻ. Giả sử bạn sử dụng Twig bạn có thể, ví dụ, làm:

<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

Cảm ơn bạn, nhưng điều đó là không thể. Chúng ta có một cấu trúc rất phức tạp và cần hàm form_widget (form), vì vậy chúng ta phải làm điều này trong backend! – snirgel

+0

Bạn đã thử thêm các trường vào cá thể 'FormBuilder' theo thứ tự mong muốn chưa? –

+0

Thats không thể. Chúng tôi có vòng khoảng 80 loại đối tượng với dependencys, thừa kế và như vậy, vì vậy chúng tôi KHÔNG THỂ thao túng những thứ như vậy bằng tay .... – snirgel

0

Theo tôi được biết, bạn muốn sử dụng chỉ form_widget (theo mẫu) trong mẫu thức.

Hãy giả sử chúng ta có hai mô hình di truyền (ModelA, ModelB) và các loại hình thức cho họ (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 
} 

Nếu bạn render formB, bạn sẽ nhận được A, B, C theo thứ tự, nhưng bạn muốn A, C, B. Để thực hiện điều đó, hãy tạo mẫu biểu mẫu và thêm tham chiếu đến ứng dụng. tệp cấu hình:

#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 %} 

Bây giờ, khi bạn tạo biểu mẫu B, bạn sẽ thấy thứ tự mong muốn và giữ mã được cấu trúc. Điều này xảy ra bởi vì mọi tiện ích chỉ hiển thị một lần, vì vậy nếu bạn hiển thị nó trước khi gọi khối chính, bạn sẽ thay đổi thứ tự của chúng.

9

Bạn có thể sắp xếp lại các lĩnh vực sử dụng gói này: https://github.com/egeloen/IvoryOrderedFormBundle

này cho phép bạn làm những việc như thế này:

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

này sẽ là trong lõi, nhưng đã bị từ chối và lôi ra thành một bó.

3

Đã có cùng một vấn đề ngay hôm nay với các yếu tố biểu mẫu đặt hàng.

Đã kết thúc với một đặc điểm đó sẽ ghi đè phương pháp finishView và sắp xếp lại các mục trong trẻ em tài sản của một 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); 
    } 
} 

Sau đó, trong loại thực hiện phương pháp getFieldsOrder:

use OrderedTrait; 

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

Đó là một giải pháp sạch, tốt! Cảm ơn! – virtualize

+0

Dễ dàng mở rộng đoạn mã này để thêm trọng số vào danh sách trường được trả về bởi getFieldsOrder, nếu ai đó cần điều này, hãy liên hệ với tôi. –

3

đây là giải pháp tôi đã đưa ra.

Tôi đã tạo một lớp mà các loại của tôi mở rộng.

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

Sau đó, bạn có thể sử dụng nó trong các lớp kế thừa của mình.

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

Lớp này kéo dài một ở trên

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

Bạn có thể làm điều đó ngay trong điều khiển của bạn trước khi bạn làm cho mẫu:

$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 công trình là tốt, tuy nhiên usort tạo ra một mảng không liên kết sẽ phá vỡ biểu mẫu hiển thị sau này.

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) }} 
Các vấn đề liên quan