问题
I have an admin class, which included another admin class.
- Symfony 2.7.9
- Sonata Admin Bundle 2.3.7
I have it structured in tabs, and the problem is that when there is a validation error in any of the fields of the embedded form is not marked in any way the tab where it is located.
This is my example code: Entity Products.php
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Products
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="AppBundle\Entity\ProductsRepository")
*/
class Products
{
//...
/**
*
* @ORM\OneToMany(targetEntity="Modules", mappedBy="products", cascade={"persist"}, orphanRemoval=true)
* @ORM\OrderBy({"position" = "ASC"})
*/
protected $module;
/**
* Constructor
*/
public function __construct()
{
$this->module= new ArrayCollection();
}
//...
/**
* Set module
*
* @param Doctrine\ORM\PersistentCollection $module
*
*/
public function setModule(\Doctrine\ORM\PersistentCollection $module) {
if (count($module) > 0) {
foreach ($module as $m) {
$this->addModule($m);
}
}
return $this;
}
/**
* Remove module
*
* @param \AppBundle\Entity\Modules $module
*/
public function removeModule(\AppBundle\Entity\Modules $module)
{
foreach ($this->module as $k => $s) {
if ($s->getId() == $module->getId()) {
unset($this->module[$k]);
}
}
}
/**
* Get module
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getModule()
{
return $this->module;
}
/**
* Add module
*
* @param \AppBundle\Entity\Modules $module
* @return Products
*/
public function addModule(\AppBundle\Entity\Modules $module)
{
$module->setProducts($this);
$this->module[] = $module;
}
//...
}
Entity Modules.php
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Modules
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="AppBundle\Entity\ModulesRepository")
*/
class Modules
{
//...
/**
* @ORM\ManyToOne(targetEntity="Products", inversedBy="module")
* @ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
protected $products;
/**
* Constructor
*/
public function __construct() {
$this->products = new ArrayCollection();
}
/**
* Set products
*
* @param \AppBundle\Entity\Products $products
* @return Modules
*/
public function setProducts(\AppBundle\Entity\Products $products = null)
{
$this->products = $products;
return $this;
}
/**
* Get products
*
* @return \AppBundle\Entity\Products
*/
public function getProducts()
{
return $this->products;
}
//...
}
Entity admin.yml
services:
sonata.admin.product.modules:
class: AppBundle\Admin\ModulesAdmin
tags:
- {name: sonata.admin, manager_type: orm, label: Products}
arguments:
- ~
- AppBundle\Entity\Modules
- 'SonataAdminBundle:CRUD'
calls:
- [ setTranslationDomain, [ProductsAdmin]]
- [ setLabelTranslatorStrategy, ["@sonata.admin.label.strategy.underscore"]]
Entity ProductsAdmin.php
<?php
namespace AppBundle\Admin;
class ProductsAdmin extends Admin {
public $supportsPreviewMode = true;
protected $formOptions = array(
'cascade_validation' => true
);
//...
protected function configureFormFields(FormMapper $formMapper) {
$formMapper
->tab('General')
->end()
->tab('Modules')
->add('module', 'sonata_type_collection', array(
'type_options' => array(
'delete' => true
)
), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position',
'admin_code' => 'sonata.admin.product.modules'
))
->end()
;
}
public function prePersist($products) {
$this->preUpdate($products);
}
public function preUpdate($products) {
$products->setModule($products->getModule());
}
//...
}
Entity ModulesAdmin.php
<?php
namespace AppBundle\Admin;
class ModulesAdmin extends Admin {
public $supportsPreviewMode = true;
protected $formOptions = array(
'cascade_validation' => true
);
protected $baseRouteName = 'admin_app_product_modules';
protected $baseRoutePattern = 'app/product-modules';
//...
}
I would like to know how to indicate the tab where the embedded form, there is a validation error in their fields is.
回答1:
This has probably already been fixed but I fixed it this way:
In my Admin Class I added:
protected $formOptions = array(
'cascade_validation' => true
);
Also in my sonata_type_collection entries I added:
'cascade_validation' => true
This causes the element on the form to add either the class 'has-error' in case of non-embedded forms, or 'error' in case of embedded sonata_type_collection inline forms, when there was a validation error.
In order to highlight the correct tab I had to use jQuery. By default the tab buttons themselves always contain the following:
<i class="fa fa-exclamation-circle has-errors hide"></i>
So it was easy enough to target this with a little bit of code and remove that 'hide' class.
// Highlight tabs if there is a validation error on an element in them
$('.tab-pane').each( function( index, element ) {
var btn = $('a[href^="#'+$(this).attr('id')+'"]');
var jumpToTab = false;
$(this).find('td, div').each(function(i, e) {
if ($(this).hasClass('error') || $(this).hasClass('has-error')) {
if (jumpToTab == false) {
btn.tab('show');
jumpToTab = true;
}
btn.find('i').removeClass('hide');
btn.addClass('error');
}
});
});
I added an 'error' class to the btn because I wanted to change the link colour as well, but that's it. Submitting the form with errors now highlights all tabs that have elements in them that have errored.
来源:https://stackoverflow.com/questions/35925712/sonataadminbundle-embebed-form-validation-error