How can I use the YUI compressor with following scenario:
routing.yml
js_route:
pattern: /foo/bar.{_format}
defaults: { _controller: FooBundle:Default:JS }
requirements:
_format: js
DefaultController.php
public function JSAction() {
// ...
// content for JS file is being generated
// ...
return $this->render('FooBundle:Default:bar.js.twig', $returnarray);
// ...
}
I know how to use it in my twig templates (e.g. {% javascripts '#FooBundle/Resources/public/js/*' filter='?yui_js' %}) but unfortunately not for above.
Any hints? Thanks!
I don't actually suggest you do this because the YUI JS compressor will be loaded on every request to the resource. But this is one way to do it anyway.
Note, in order to keep the example simple I've excluded any extra code to properly determine your web root and location of the jar file.
$path = $this->container->getParameter('kernel.root_dir');
$ac = new \Assetic\Asset\AssetCollection(array(
new \Assetic\Asset\FileAsset($path . '/../src/WebBundle/Resources/public/js/jquery.longclick.js')
), array(
new \Assetic\Filter\Yui\JsCompressorFilter($path . '/Resources/java/yuicompressor-2.4.7.jar')
));
$compressJS = $ac->dump();
return new Response($compressJS, 200, array('Content-Type' => 'text/javascript'));
Also note, you're not just limited to FileAsset(). There are other classes available like StringAsset(), etc, so you can build content dynamically.
Related
I'm trying to edit my tables content by following this example DataTables example
In my twig page I've added this script at the end:
$(document).ready(function() {
/* Init DataTables */
var oTable = $('.dataTable').dataTable();
/* Apply the jEditable handlers to the table */
oTable.$('td').editable( 'editable_ajax.php', {
"callback": function( sValue, y ) {
var aPos = oTable.fnGetPosition( this );
oTable.fnUpdate( sValue, aPos[0], aPos[1] );
},
"submitdata": function ( value, settings ) {
return {
"row_id": this.parentNode.getAttribute('id'),
"column": oTable.fnGetPosition( this )[2]
};
},
"height": "auto",
"width": "auto"
} );
} );
the file editable_ajax.php is in the folder where my twig page is.
When I try to edit a cell I see with the debugging tool that the 'editable_ajax.php' file is not found, Can someone tell me where I should place it please ?
I'm sorry to say, but you seem to not have a good grasp of how templating and Symfony in general work. You're mixing very different things (PHP code, twig templates, Javascript code).
So, first read the Symfony Book. I would also suggest reading up on Javascript.
Some mistakes:
PHP files should never be in the "views" folder (aka. with twig files)
Javascript runs on the client side so you need to think about URLs when calling server-side code (aka. php code) NOT filesystem paths.
Javascript (jQuery is just a library) should not be in a twig file, but it's own *.js file and linked with a <script> html tag.
In my dev environment after adding a response listener the content type of my css files switched from text/css to text/html. My goal is just to add some caching headers to all responses of my symfony application.
Service definition:
response_listener:
class: AppBundle\EventListeners\ResponseListener
tags:
- { name: kernel.event_listener, event: kernel.response }
Service class:
<?php
namespace AppBundle\EventListeners;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
class ResponseListener
{
public function onKernelResponse(FilterResponseEvent $event)
{
// while testing I do nothing special here
$response = $event->getResponse();
$event->setResponse($response);
}
}
Assetic config:
assetic:
debug: "%kernel.debug%"
use_controller: true
bundles: [ AppBundle ]
filters:
cssrewrite: ~
Twig tag:
{% stylesheets
'bundles/app/css/login.css'
filter='cssrewrite' %}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}"/>
{% endstylesheets %}
With text/html as the content type the css is not rendered.
Removing just the service definition makes it work correctly again.
In prod environment it works with or without the response listener and js files are no problem at all.
Any ideas?
I had a really similar issue and although I didn't went to trace it exactly on the core bundles of symfony, I think this is due to the fact that, on development instance, assetic do use a controller to render the CSS.
I actually stopped looking at the moment I found, that, like you, my config_dev.yml stated :
assetic:
use_controller: true
So I figured out that when you try to play with the response object in symfony, the requested format gets somehow lost while listening on the response. Symfony's own ResponseListener seems to set text/html as a defaullt because there is no content type defined.
The fix is quite easy though :
In the class ResponseListener, our listening function become
public function onKernelResponse(FilterResponseEvent $event)
{
$response = $event->getResponse();
// We do get the params of the route
$route_params = $event->getRequest()->get('_route_params');
// And we figure out if it should be in a specific format
if(isset($route_params['_format'])) {
// getMimeType function on the Request object come in handy for this job
$format = $event->getRequest()->getMimeType($route_params['_format']);
// Then we just reinstate the right Content Type
$response->headers->set('Content-Type', $format);
}
$event->setResponse($response);
}
While you will never have this issue in production environnement like you state it, because your assets are dumped by the command line assetic tool, which is not a controller.
And actually, if you do something like this in your ResponseListener
die($event->getRequest()->get('_controller'));
And that you navigate to a css file by its direct url you would see this display :
Which totally validate the fact that the css gets constructed on the fly by the render view of assetic bundle controller when you have that configuration stated above.
Problem
I need to generate CSS file while page is rendering (custom colors for each user). In order to achieve that I made an action to render the file and and put the route as a reference, like that:
public function styleAction()
{
$backgroundColor = $this->getUser()->getCompany()->getBackgroundColor();
if(!$backgroundColor || $backgroundColor =="")
$backgroundColor = '#b5dea2';
$response = new Response();
$response->setContent($this->render('*WHAT_TO_PUT_HERE*:style.css.twig',array('backgroundColor' => $backgroundColor)));
$response->headers->set('Content-Type', 'text/css');
return $response;
}
Route:
css_route:
path: /css/mainStyle
defaults: { _controller: AcmeMainBundle:Default:style }
Question:
What to write in place of "WHAT_TO_PUT_HERE" in order to access to the file located under /web/css/style.css.twig.
Put the file in your Bundles Resources\views directory.
I've got some symfony template files with <script> chunks, obviously this needs to be in the head.
these chunks of javascript make use of helpers like url_for and also echo out symfony template variables.
I need to be able to load this javascript using include_javascript or similar but what is the best way to still use the symfony templating functions and access the variables I need to generate the script while loading it into the head not the body of the page.
In this case I use a particular Symfony module, that fills JavaScript variables with PHP code.
To do so, you can create a module called "javascript" for example, which has a single action in it. The template associated to this action must be have the following name : ...Success.js.php.
In this template, you can fill your JavaScript variables like this :
var global = {
misc: {
userCulture : "<?php echo $sf_user->getCulture() ?>",
serverName : "<?php echo $_SERVER["SERVER_NAME"]?>",
},
...
}
Then, in your *appName*Configuration.class.php (located in the config folder of your app), you must add the following code :
class indexConfiguration extends sfApplicationConfiguration
{
public function configure()
{
$this->dispatcher->connect('context.load_factories', array($this, 'listenToContextLoadFactoriesEvent'));
}
public function listenToContextLoadFactoriesEvent(sfEvent $event)
{
$event->getSubject()->getResponse()->addJavascript($event->getSubject()->getRouting()->generate('javascript_variables'));
}
}
Then, you must add the following route to your routing.yml file :
javascript_variables:
url: /*moduleName*/*actionName*.:sf_format
param: { module: *moduleName*, action: *actionName*, sf_format: js }
Now, you're able to access these JavaScript variables in any of your js files, i.e. :
$(document).ready(function() {
alert(global.misc.userCulture);
});
I'm using Symfony2 to develop a application that is to be translatable. The application has Assetic enabled to minify and combine *.js and *.css files. However, I have a jQuery plugin I wrote, that has literal strings in it. For example, consider the following code:
$('<p>Are you sure you want to proceed?</p>').dialog({
buttons: {
"Yes" : function() {
// ...
},
"No" : function() {
// ...
}
}
});
In the above snippet, "Are you sure...", "Yes" and "No" will always be English, and I can't use Twig templating in the .js file to translate it using something like: {{ "yes"|trans }}
What I want to know is, what would be the best way to use Twig to leverage the built in Symfony2 translation mechanism, to translate the literal strings in my JS scripts.
Is there a way to create for example: myscript.js.twig files?
Is there a way to create for example: myscript.js.twig files?
It seems a bad idea.
You can check https://github.com/willdurand/BazingaExposeTranslationBundle
or create it yourself, for example include this in your template:
<script type="text/javascript">
var translations = {
// ...
'yes' : {{ 'yes' | trans }},
// ...
}
</script>
then if your javascript file is included just before </body> you can use translations variable in it.
Here is my solution (Tested on Symfony 4 and 5):
First, we create a controller that will create JS file with all translations according to the current variable locale:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Yaml\Yaml;
/**
* Translation controller.
*/
class TranslationController extends AbstractController
{
/**
* #Route("/translation.js", name="translation")
*/
public function index(Request $request)
{
$locale = $request->getLocale();
$file = __DIR__.'/../../translations/messages.'.$locale.'.yaml';
$parsed = Yaml::parse(file_get_contents($file));
$translations = $this->renderView(
'translation/translation.js.twig',
array(
'json' => json_encode($parsed)
)
);
return new Response($translations, 200,
array('Content-Type' => 'text/javascript')
);
}
}
Then we create a TWIG template to render (/templates/translation/translation.js.twig):
var trans = JSON.parse('{{ json|raw }}');
We place our dynamic translation file in the template before other assets:
<script src="{{ path('translation') }}"></script>
For sample translation file /translations/messages.pl.yaml:
projects: Projekty
medium: Średnio
month:
january: Styczeń
february: Luty
We can display our translation in any JS file:
console.log(trans['month']['january']);
console.log(trans['medium']);
I hope it will be useful to someone
I was searching something to make twig.js work with translations which seems to me like the best solution. Still searching though.
In the meantime, I'm using this jsgettext which is a gettext implementation in Javascript, by Joshua I. Miller. I've uploaded back to github since the original repo is down.
<script language="javascript" src="/path/LC_MESSAGES/myDomain.json"></script>
<script language="javascript" src="/path/Gettext.js"></script>
You load your translation files into your DOM and jsgettext can parse it:
function _(msgid) { return gt.gettext(msgid); }
alert(_("some string"));
To get the path of your translation files from Symfony, you'll have to make some php/twig extension around the Translator service but it works great without duplicating your translation resources.