Symfony 3与Sonata动态形成更新。基于选择字段的选择值

时间:2017-06-23 23:05:01

标签: php jquery ajax symfony sonata

我想要做什么。我有帖子,类别和属性。我可以在我的帖子管理页面上创建具有许多属性的类别的类别。在我的帖子中,我可以选择一个类别。当我选择类别(选择字段)时,在此之后我将所选的属性显示为(输入字段)。

我的表单上的下拉列表和文本字段:

Dropdown and Textfield on my Form

当我保存所选类别的帖子时,我会在提交属性输入字段后看到。这很有效。

这是必要但不好。好的,我需要一个带有ajax的解决方案。没有Symfony没有问题,但有一个大的^^

我谷歌这看,我需要一个CRUD控制器和我的Form TypeClass中的一个事件。

我的TypeClass:

class PropertiesType extends AbstractType
{

    public $em;

    private $session;

    public function __construct(EntityManagerInterface $em,Session $session)
    {
        $this->em = $em;
        $this->session = $session;

    }

    protected function generateFormInputs(FormEvent $event){

        $form = null;

        if(!is_array($event->getData()) && ($event->getData() === null || !$event->getData()->getCategory())){
            return false;
        }

        if(!is_array($event->getData())){
            $furniture = $event->getData();
            $form = $event->getForm();
        }else{
            $pp = $this->em->getRepository('ProductBundle:Furniture')->findOneBy(array('id' => $event->getData()['furniture_id']));
            $pp->setCategory($this->em->getRepository('ProductBundle:Category')->findOneBy(array('id' => $event->getData()['category_id'])));
            $event->setData($pp);
            $furniture = $event->getData();
            $form = $event->getForm();
        }


        if($furniture !== null){

            foreach($furniture->getCategory()->getProperties() as $val){

                $repo = $this->em->getRepository('ProductBundle:FurnitureProperties')->findOneBy(array('furniture' => $furniture->getId(), 'property' => $val->getId()));

                if($repo === null){
                    $repo = new FurnitureProperties();
                    $repo->addProperty($val);
                    $repo->addFurniture($furniture);
                    $repo->setPropertyId($val->getId());
                    $repo->setCurrentLocale($this->session->get('_locale'));
                }

                $form->add('properties_'.$val->getId(), 'text', array(
                    'mapped' => false,
                    'label' => $val->getName(),
                    'data' => $repo,
                    'required' => false
                ));
            }

        }
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {

            if($event->getData() !== null){

                foreach($event->getData() as $key => $val){
                    $obj = '';
                    $obj = $event->getForm()->get($key)->getData();

                    if($val !== ''){
                        $obj->setText($val);


                        $this->em->persist($obj);
                        $obj->mergeNewTranslations();
                        $this->em->flush();
                    }else{
                        $this->em->remove($obj);
                        $this->em->flush();
                    }
                }
            }

        });

        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $this->generateFormInputs($event);
        });
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'ProductBundle\Entity\Furniture',
            'empty_data' => new FurnitureProperties(),
        ));
    }

}

我的CRUD控制器:

<?php

namespace ProductBundle\Controller;

use ProductBundle\Form\Type\PropertiesType;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

class FurnitureCRUDController extends Controller
{
    public function ajaxAction($furniture_id, $category_id, Request $request)
    {
        $form = $this->createForm(PropertiesType::class, array(
            'furniture_id' => $furniture_id,
            'category_id' => $category_id
        ));



        $form->handleRequest($request);


        return $this->render('form/fields.html.twig',
            array(
                'form' => $form->createView()
            )
        );


    }
}

我的树枝模板:

{% block properties_widget %}

    {% if id is defined %}
        {% set token = id|split('_')[0] %}

        <script type="text/javascript">
            jQuery(document).ready(function($){
                $('#{{ token }}'+'_category').change(function(){

                    var current_element = this;

                    jQuery.ajax({
                        url : '/admin/product/furniture/ajax/{{ form.vars.value.id }}/'+jQuery(current_element).val()+'?uniqid={{ token }}',
                        type: 'post',
                        data: $("form").serialize(),
                        success: function(html) {
                            jQuery('.category_replacement').html(html);

                        }
                    });
                });
            });
        </script>

    {% endif %}


    <div class="category_replacement">
        {% for fields in form.children %}

            {% set attr = fields.vars %}

            <div id="sonata-ba-field-container-{{ attr.id }}" class="form-group">
                <label for="{{ attr.id }}" class="control-label {{ attr.required == true ? 'required' : '' }}">{{ attr.label }}</label>

                <div class="sonata-ba-field sonata-ba-field-standard-natural">
                    <input class="form-control" name="{{ attr.full_name }}" id="{{ attr.id }}" value="{{ attr.value }}" {{ attr.required == true ? 'required="required"' : '' }}>
                </div>
            </div>

        {% endfor %}
    </div>

{% endblock %}

如果我这样做的话。我得到了这个结果(浏览器)。

<div class="category_replacement">

    <div id="sonata-ba-field-container-properties_properties_1" class="form-group">
        <label for="properties_properties_1" class="control-label ">höhe</label>

        <div class="sonata-ba-field sonata-ba-field-standard-natural">
            <input class="form-control" name="properties[properties_1]" id="properties_properties_1" value="">
        </div>
    </div>

    <div id="sonata-ba-field-container-properties__token" class="form-group">
        <label for="properties__token" class="control-label "></label>

        <div class="sonata-ba-field sonata-ba-field-standard-natural">
            <input class="form-control" name="properties[_token]" id="properties__token" value="AhNHvQrq_8f6ObAOTB1MmbX7Nv_FBmFsgQe3z_sH7qg">
        </div>
    </div>

</div>

My Original但看起来如此(浏览器):

<div class="category_replacement">

    <div id="sonata-ba-field-container-s594d9b1861e8e_furniture_properties_1" class="form-group">
        <label for="s594d9b1861e8e_furniture_properties_1" class="control-label ">height</label>

        <div class="sonata-ba-field sonata-ba-field-standard-natural">
            <input class="form-control" name="s594d9b1861e8e[furniture][properties_1]" id="s594d9b1861e8e_furniture_properties_1" value="">
        </div>
    </div>

</div>

有什么问题? Ajax请求没有唯一的ID?我想,没问题,我会用JavaScript改变它。

但提交表格后。 Symfony不知道我的输入字段。为什么呢?

当我使用没有此Ajax解决方案的表单时。我可以在表单中添加实体,并在提交后使用它们。但是当我使用ajax解决方案时,我无法与实体合作,我认为这很糟糕。

唯一的选择是将Property ID添加到输入字段的name属性,并从db加载它。

如果有帮助的话。我的作曲家要求:

"php": ">=5.5.9",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/orm": "^2.5",
"friendsofsymfony/rest-bundle": "^2.2",
"incenteev/composer-parameter-handler": "^2.0",
"knplabs/doctrine-behaviors": "^1.4",
"nelmio/api-doc-bundle": "^2.13",
"sensio/distribution-bundle": "^5.0.20",
"sensio/framework-extra-bundle": "^3.0.2",
"sonata-project/admin-bundle": "3.19.0",
"sonata-project/doctrine-orm-admin-bundle": "^3.1",
"sonata-project/google-authenticator": "^2.0",
"sonata-project/media-bundle": "^3.5",
"sonata-project/translation-bundle": "^2.1",
"sonata-project/user-bundle": "dev-master",
"stof/doctrine-extensions-bundle": "^1.2",
"symfony/assetic-bundle": "^2.8",
"symfony/monolog-bundle": "^3.1.0",
"symfony/polyfill-apcu": "^1.0",
"symfony/swiftmailer-bundle": "^2.3.10",
"symfony/symfony": "3.3.*",
"twig/twig": "1.34.3"

是的,我知道。带有ID的解决方案不是最好的:

'properties_'.$val->getId()

但这是另一个问题:)

0 个答案:

没有答案