2016-01-23 21 views
11

Benim modelimde bir Recipe varlık ve Hammadde var.Symfony form sırası KoleksiyonType alanı

/** 
* @ORM\OneToMany(targetEntity="Ingredient", mappedBy="recipe", cascade={"remove", "persist"}, orphanRemoval=true) 
* @ORM\OrderBy({"priority" = "ASC"}) 
*/ 
private $ingredients; 

İçerik tarafı olan: Reçete varlık olarak, ilişki böyle tanımlanır

/** 
* @ORM\ManyToOne(targetEntity="Recipe", inversedBy="ingredients") 
* @ORM\JoinColumn(name="recipe_id", referencedColumnName="id") 
*/ 
private $recipe; 

Tarif için CRUD kontrolörü üzerinde çalışıyorum ve ben kullanıcı dinamik malzemeyi eklemek mümkün olmak istiyorum . Ayrıca, kullanıcılara reçete içindeki önceliklerini (siparişi) ayarlamak için öğeleri sürükleyip bırakmasını istiyorum. Bunun için CollectionType form alanını kullanıyorum.

ve öğretici olarak bu sayfayı:

http://symfony.com/doc/current/cookbook/form/form_collections.html

ekleme ve tarifin gösteren mükemmel şimdiye kadar çalışıyoruz, ancak aşağıda tarif çalışacağım Düzen/Güncelleme eylemi, bir sorun vardır:

denetleyici olarak

, ben varlık yüklemek ve bunun gibi form oluşturmak: priori yana

public function updateAction($id, Request $request) 
    { 
     $em = $this->getDoctrine()->getManager(); 
     $recipe = $em->getRepository('AppBundle:Recipe')->find($id); 


     $form = $this->createEditForm($recipe); 
     $form->handleRequest($request); 

     ... 

    } 

ty DB'ye kaydedilir ve @ORM\OrderBy({"priority" = "ASC"}) var, içeriklerin ilk yüklemesi ve görüntüsü iyi çalışıyor. Ancak, kullanıcı etraftaki malzemeleri sürükleyip bırakırsa, öncelik değerleri değişir. Form doğrulama hatalarının olması ve formun tekrar tekrar gösterilmesi gerekiyorsa, öncelikli değerler güncellenmiş olsa bile formdaki bileşenler eski düzende görüntülenir.

Örneğin, DB ilk Madde aşağıdaki => öncelikli değerler vardır:

  • A => 1
  • B => 2
  • C => 3

Form satırları sırayla görüntülenir: A, B, C; Kullanıcı sırasını değiştirir sonra

, ben:

  • B => 1
  • A => 2
  • C => 3

ancak form sıraları hala gösterildi A, B, C olarak;

Formun A, B, C sıralarıyla başlatıldığını ve priority güncelleştirmesinin ArrayCollection öğesinin sırasını değiştirmediğini anlıyorum. Ama ben (neredeyse) nasıl değiştireceğimi bilmiyorum. Ben şimdiye kadar denedim ne

: Zaten girişine sahip formdaki setData() kullanmasına izin verilmez görünüşte olarak

$form->getData(); 
// sort in memory 
$form->setData(); 

Bu, çalışmaz.

Satırları sıralamak için bir DataTransformer ayarlamayı denedim, ancak form yeni siparişi yoksayar.

Ayrıca, satırları sıralamak için FormType sınıfındaki PRE/POST gönderme işleyicilerini kullanmayı denedim, ancak form hala yeni siparişi yoksayar.

Tarif bütünlükte

, kontrolörde, sonra bellekte ArrayCollection sıralar sortIngredients() yöntemi

public function sortIngredients() 
    { 
     $sort = \Doctrine\Common\Collections\Criteria::create(); 
     $sort->orderBy(Array(
      'priority' => \Doctrine\Common\Collections\Criteria::ASC 
    )); 

     $this->ingredients = $this->ingredients->matching($sort); 

     return $this; 
    } 

tanımlar:

$form = $this->createEditForm($recipe); 
    $form->handleRequest($request); 

    $recipe->sortIngredients(); 

    // repeatedly create and process form with already sorted ingredients 
    $form = $this->createEditForm($recipe); 
    $form->handleRequest($request); 

    // ... do the rest of the controller stuff, flush(), etc 

(tür) bu işleri son şey şudur

Bu çalışır, ancak form iki kez oluşturulur ve işlenir ve dürüstçe bir kesmek gibi görünüyor ...

Sorunu çözmenin daha iyi bir yolunu arıyorum.

cevap

9

Form türünüzün finishView yöntemini kullanmanız gerekir.

İşte kod örneği:

public function finishView(FormView $view, FormInterface $form, array $options) 
{ 
    usort($view['photos']->children, function (FormView $a, FormView $b) { 
     /** @var Photo $objectA */ 
     $objectA = $a->vars['data']; 
     /** @var Photo $objectB */ 
     $objectB = $b->vars['data']; 

     $posA = $objectA->getSortOrder(); 
     $posB = $objectB->getSortOrder(); 

     if ($posA == $posB) { 
      return 0; 
     } 

     return ($posA < $posB) ? -1 : 1; 
    }); 
} 
+3

çalışır !!! Bu konuda yarım gün geçirdim ... teşekkür ederim. Çok kötü, Symfony web sitesinde bu yöntemle ilgili çok fazla belge yok. – Karolis

İlgili konular