2012-04-04 70 views
16

我想在自定義Symfony 2表單字段類型擴展中使用JavaScript。所以,我有枝杈擴展模板是這樣的:Symfony 2自定義表單字段類型:如何只添加一次javascript和css一次?

{% block some_widget %} 
    <input ... /> 

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

但我想在我的HTML有這些腳本和鏈接標籤只有一次,最好是在頭標記,沒有對矯正基礎模板。我試圖擴展Twig塊,但我無法訪問表單模板中的操作模板塊。或者可能是這樣的:

{# 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做到這一點?

P.S.對不起,我的英語不好。

+0

爲什麼你不想修改基本模板?這*是設置你想要導入哪個js \ css文件的地方 – tamir 2012-04-06 21:19:17

+2

我想創建一些自包含表單控件擴展包,並且在AppKernel.php中只啓用一次這個包。此外,如果小部件在當前頁面中沒有用處,我不想包含js/css。 – 2012-04-13 08:18:07

+0

這似乎是Symfony中的一個缺失功能​​(直到現在)。也許我們應該從[django widget媒體](https://docs.djangoproject.com/en/dev/topics/forms/media/#assets-as-a-static-definition)啓發,它只包含小部件禮物 – 2015-11-28 06:51:19

回答

0

這就是我使用它的方式。希望這是你要找的。

base.html.twig

<head> 
    {% block stylesheets %} 
     css... 
    {% endblock %} 
</head> 

foo.html.twig

{% extends '::base.html.twig' %} 

{% block stylesheets %} 
    {{ parent() }} 

    css that you need in foo.html.twig 

{% endblock %} 
+1

是的,這是常規視圖的常用方法(我使用它)。但是這不適用於表單類型模板。 – 2012-04-13 08:12:27

1

,最好的辦法是提供單獨的模板使用CSS &腳本加載。 隨着自述所以唯一開發商的意見將必須做的是

{% block stylesheets %} 
    {{ parent() }} 

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

{% endblock %} 

或試圖攔截形式DI渲染和增加的資產。但是如果可能的話,這樣做更難。

6

我不得不寫,需要JavaScript的一個自包含表單控件,我是能夠實現你正在試圖通過event_dispatcher監聽的kernel.response做的JavaScript在Symfony\Component\HttpFoundation\Response的末尾添加。這是我的表單類型的一個片段:

<?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定義表單類型,它看起來像這樣:

acme.form.acme_file_type: 
    class: AcmeBundle\Form\AcmeFileType 
    arguments: 
     - @twig 
     - @event_dispatcher 
    tags: 
     - { name: form.type, alias: acmefile } 

所以,現在,每次你建立一個形式acmefile的JavaScript將被追加到<body>。雖然這個解決方案並不妨礙的javascript從多次出現,但您應該很容易就能夠改善這一點以適應您的需求。

如果您願意,也可以使用$response對象來改變標頭

+0

看起來合法。 Symfony使用類似的技巧來加載Web調試工具欄。 – MauganRa 2017-04-20 01:03:51

0

我發現在其他情況下很多人使用了一些「髒」的方法。 我們檢查客戶端腳本的加載。如果我們有一個zlkladr.js文件,它有一個全局對象'zlkladr'

{% block our_widget %} 
{% spaceless %} 
    ... 
    <script> 
    // We must load the script only once, even if many widgets on form 
    if (!window.zlkladr) { 
     document.write('<script src="{{ asset('bundles/kladr/js/zlkladr.js') }}"></sc'+'ript>'); 
    } 
    </script> 
{% endspaceless %} 
{% endblock %} 
相關問題