首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Symfony 2自定义表单字段类型:如何只添加一次javascript和css?

Symfony 2自定义表单字段类型:如何只添加一次javascript和css?
EN

Stack Overflow用户
提问于 2012-04-04 18:30:48
回答 5查看 9.6K关注 0票数 19

我想在自定义Symfony 2表单字段类型扩展中使用javascript。所以,我有这样的Twig扩展模板:

代码语言:javascript
复制
{% block some_widget %}
    <input ... />

    <script src="some.js"></script>
    <link href="some.css" />
{% endblock %}

但是我只想让这些脚本和链接标签在我的HTML中出现一次,最好是在head标签中,而不修改基本模板。我试图扩展Twig块,但我无法访问表单模板中的动作模板块。或者像这样:

代码语言:javascript
复制
{# widget tempate #}
{% block some_widget %}
    <input ... />

    {{ use_javascript('some.js') }}
    {{ use_css('some.css') }}
{% endblock %}

{# main action template #}
...
<head>
{{ dump_javascripts() }}
{{ dump_css() }}
</head>
...

如何使用Symfony 2 Forms + Twig做到这一点?

另外,很抱歉我的英语不好。

EN

回答 5

Stack Overflow用户

发布于 2014-12-31 03:10:53

我不得不写一个需要javascript的自包含表单小部件,我能够通过监听kernel.responseevent_dispatcherSymfony\Component\HttpFoundation\Response的末尾附加javascript来实现您正在尝试做的事情。下面是我的表单类型的一个片段:

代码语言:javascript
复制
<?php

namespace AcmeBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;

class AcmeFileType extends AbstractType{

  private $twig;
  private $dispatcher;

  public function __construct(\Twig_Environment $twig, EventDispatcherInterface $dispatcher){
    $this->twig = $twig;
    $this->dispatcher = $dispatcher;
  }

  public function buildView(FormView $view, FormInterface $form, array $options){

    $javascriptContent = $this->twig->render('AcmeBundle:Form:AcmeFileType.js.twig', array());

    $this->dispatcher->addListener('kernel.response', function($event) use ($javascriptContent) {

      $response = $event->getResponse();
      $content = $response->getContent();
      // finding position of </body> tag to add content before the end of the tag
      $pos = strripos($content, '</body>');
      $content = substr($content, 0, $pos).$javascriptContent.substr($content, $pos);

      $response->setContent($content);
      $event->setResponse($response);
    });

  }

  ... 

当您在services.yml中定义表单类型时,它如下所示:

代码语言:javascript
复制
acme.form.acme_file_type:
    class: AcmeBundle\Form\AcmeFileType
    arguments:
        - @twig
        - @event_dispatcher
    tags:
        - { name: form.type, alias: acmefile }

所以现在,每次你用acmefile构建表单时,javascript都会被附加到<body>。这个解决方案并没有阻止 javascript被多次呈现,但是你应该可以很容易地改进它来满足你的需要。

如果愿意,您还可以尝试使用$response对象来修改headers

票数 10
EN

Stack Overflow用户

发布于 2012-07-03 19:51:20

最好的方法是提供css和脚本加载单独的模板。使用自述文件中的注释,所以开发人员唯一必须做的就是

代码语言:javascript
复制
{% block stylesheets %}
  {{ parent() }}

  include "@MyBestBundle/Resources/view/styles.html.twig"

{% endblock %}

或者尝试使用DI截取表单渲染并添加资产。但如果可能的话,这样做会更加困难。

票数 1
EN

Stack Overflow用户

发布于 2020-05-17 19:50:40

我的方法是创建一个自定义的twig扩展,在其中我将JS添加到缓冲区中,并在表单呈现期间,稍后将其转储到我的布局的末尾。

如下所示:

代码语言:javascript
复制
<?php

namespace AppBundle\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class WysiwygExtension extends AbstractExtension
{
    /**
     * @var array
     *
     * A pool of elements IDs for Wysiwyg binding.
     */
    private $wysiwygElements = [];

    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return array(
            new TwigFunction('addWysiwygBinding', [$this, 'addWysiwygBinding']),
            new TwigFunction('popWysiwygBindings', [$this, 'popWysiwygBindings']),
        );
    }

    public function addWysiwygBinding(string $id): void
    {
        $this->wysiwyglements[] = $id;
    }

    public function popWysiwygBindings(): array
    {
        $elements = array_unique($this->wysiwygElements);

        $this->wysiwygElements = [];

        return $elements;
    }
}

然后是form-fields.html.twig

代码语言:javascript
复制
...
{% block wysiwyg_widget %}
{% apply spaceless %}
    {{ form_widget(form) }}
    {% do addWysiwygBinding(id) %}
{% endapply %}
{% endblock %}
...

然后是layout.html.twig

代码语言:javascript
复制
<!DOCTYPE html>
<html>
  <head>
    ...
  </head>
  <body>
    ...

        {% set ids = popWysiwygBindings() %}

        {% if ids is not empty %}
            {% javascripts
                'bundles/admin/plugins/wysiwyg_1.js'
                'bundles/admin/plugins/wysiwyg_2.js'
            %}
                <script type="text/javascript" src="{{ asset_url }}"></script>
            {% endjavascripts %}
        {% endif %}

        {% for id in ids %}
            {{ include('_wysiwyg.html.twig', { id: id }) }}
        {% endfor %}
  </body>
</html>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10009352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档