2012-04-04 17 views
16

Ich möchte Javascript in benutzerdefinierten Symfony 2 Formularfeldtyp Erweiterung verwenden. So habe ich Zweig Erweiterung Vorlage wie folgt aus:Symfony 2 benutzerdefiniertes Formular Feldtyp: Wie fügt man Javascript und CSS nur einmal hinzu?

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

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

Aber ich will nur diese Skript und Link-Tags haben, einmal in meinem HTML, idealerweise im Head-Tag, ohne Basisvorlage modifing. Ich habe versucht, Zweigblöcke zu erweitern, aber ich habe keinen Zugriff auf Aktionsvorlagenblöcke in der Formularvorlage. Oder vielleicht etwas in der Art:

{# widget tempate #} 
{% block some_widget %} 
    <input ... /> 

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

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

Wie geht das mit Symfony 2 Forms + Twig?

P.S. Entschuldigung für mein schlechtes Englisch.

+0

Warum möchten Sie die Basisvorlage nicht ändern? Dies * ist * der Ort, an dem festgelegt wird, welche js \ css-Dateien importiert werden sollen. – tamir

+2

Ich möchte ein selbstenthaltendes Formular-Widget-Erweiterungspaket erstellen und dieses Paket nur einmal in AppKernel.php aktivieren. Außerdem möchte ich js/css nicht enthalten, wenn das Widget in der aktuellen Seite nicht verwendet wird. –

+0

Dies scheint eine fehlende Funktion in Symfony zu sein (bis jetzt). Vielleicht sollten wir von [django widget media] (https://docs.djangoproject.com/de/dev/topics/forms/media/#assets-as-a-static-definition), die einmal die Assets nur dann einbezieht, wenn die widget present –

Antwort

0

So benutze ich es. Hoffe, dass es das ist, wonach du suchst.

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

Ja, das ist der normale Weg für normale Viewtates (und ich benutze es). Dies funktioniert jedoch nicht mit Formularvorlagen. –

1

Der beste Weg ist es, die eigene Vorlage mit CSS & Skripte laden zu liefern. mit den Kommentaren in readme so einzigereinzigeeinziges, was Entwicklern werden muss

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

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

{% endblock %} 

oder versuchen, das Formular mit DI-Rendering abzufangen und die Vermögenswerte hinzuzufügen. Aber es ist schwieriger zu tun, wenn möglich zu implementieren.

6

Ich hatte eine in sich geschlossene Form Widget zu schreiben, die JavaScript erfordert, ich war in der Lage zu erreichen, was Sie durch die event_dispatcher hören auf dem kernel.response zu tun versuchen das Javascript am Ende des Symfony\Component\HttpFoundation\Response anzuhängen. Hier ist ein Ausschnitt meiner Form Typ:

<?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); 
    }); 

    } 

    ... 

Wenn Sie Ihre Formulartyp in Ihrem services.yml definieren sieht es wie folgt aus:

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

So, jetzt, jedes Mal wenn Sie ein Formular erstellen mit acmefile die Javascript wird an die <body> angehängt. Diese Lösung verhindert nicht das Javascript von vorhanden mehrere Male obwohl, aber Sie sollten leicht in der Lage sein, dies zu verbessern, um Ihren Bedürfnissen zu entsprechen.

Sie können auch mit dem $response Objekt spielen, um die Header zu ändern statt, wenn Sie es wünschen.

+0

Scheint echt. Symfony verwendet einen ähnlichen Trick, um die Web-Debug-Symbolleiste zu laden. – MauganRa

0

Ich fand eine "schmutzige" Methode, die von vielen Menschen in anderen Situationen verwendet wird. Wir überprüfen das Laden des Skripts auf der Client-Seite. Falls wir eine zkllad.js-Datei haben, die ein globales Objekt 'zlkladr' hat

Verwandte Themen