SonataAdminBundle嵌入表单验证错误

时间:2016-03-10 19:39:24

标签: php forms validation symfony sonata-admin

我有一个管理类,其中包括另一个管理类。

  • Symfony 2.7.9
  • Sonata Admin Bundle 2.3.7

我在选项卡中对其进行了结构化,问题是当嵌入表单的任何字段中存在验证错误时,不会以任何方式标记它所在的选项卡。

这是我的示例代码: 实体 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;

    }

    //...

}

实体 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;
    }

    //...
}

实体 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"]]

实体 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());
    }

    //...

}

实体 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';

    //...

}

我想知道如何指示嵌入表单的选项卡,其字段中存在验证错误。

1 个答案:

答案 0 :(得分:2)

这可能已经修复,但我这样解决了:

在我的管理课程中,我添加了:

protected $formOptions = array(
    'cascade_validation' => true        
);

同样在我的sonata_type_collection条目中,我添加了:

'cascade_validation' => true

这导致表单上的元素在非嵌入表单的情况下添加类'has-error',或在嵌入的sonata_type_collection内联表单的情况下添加'error',当存在验证错误时。

为了突出显示正确的选项卡,我必须使用jQuery。默认情况下,选项卡按钮本身始终包含以下内容:

<i class="fa fa-exclamation-circle has-errors hide"></i>

所以很容易用一点代码来解决这个问题并删除那个'hide'类。

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

我在btn中添加了一个'错误'类,因为我也希望改变链接颜色,但就是这样。现在,提交包含错误的表单会突出显示其中包含错误的元素的所有选项卡。