how can I use php variables and symfony helpers in javascript - symfony-1.4

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

Related

DataTables editable (where to put the editable_ajax.php file)

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.

(AngularJS) Only one less file for entire Website

I am a beginner with AngularJS and I have a little problem, I installed grunt-contrib-less to support less files instead css but now I have to declare all less styles that will be compiled into only one css file.
But my problem is normally when I'm using less, I write some code for a specific page, and here I have to write the style code for all pages. This is confusing and not really maintanable so is there a best practice to organize less styles?
I tought that there may be multiple solution:
Apply a class to body tag and change it with I don't know what
(controller, services or other)
(Import LESS file only for one page)
Generate multiple css file depending which style is compiled (but I can't do this because I can't configure grunt correctly)
Do this with DOM manipulation (but it don't find it beautifull because I think Angular must have a good way to solve that problem)
Could you explain me how to have different style for differents views ? I don't want to have the same style for all links in all views and without create hundreds classes I don't know how to do that.
Use directive
and add whatever variables/code/logic you want to add
HTML template(directive) of style can be added to your view and after compile you will get different ui for all your views
for reference read
angular directive
I solve my problem by adding specific class on body tag depending the route.
I put a variable in rootScope called 'pageStyle' with correspond to the classname that I want. This variable is updated automatically when route change (see run function). There is an event when the route change ($stateChangeSuccess or $routeChangeSuccess depending if you are using ngRoute or -angularui-routeur).
In my case i would like to add the name of the route but you can do it with the controller name or something else.
Here is an example
This is the routes :
angular
.module('frontApp', [])
.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider, $mdThemingProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: '../views/home.html',
controller: function ($scope) {
$scope.msg = 'Xavier';
}
})
.state('form', {
url: '/form',
templateUrl: '../views/form.html',
controller: 'FormCtrl'
});
}])
And in the run function you will see the event bound to adapt the class when route change :
.run(function($rootScope) {
$rootScope.pageStyle = '';
// Watch state and set controller name in pageStyle variable when state change
$rootScope.$on('$stateChangeSuccess', function(event, toState) {
event.preventDefault();
if (toState && toState.name && typeof toState.name === 'string'){
$rootScope.pageStyle = toState.name;
} else {
$rootScope.pageStyle = '';
}
});
});
Extra informations :
Note that the event called when route change is different if you are using ngroute. use "$routeChangeSuccess" if you use ngRoute and "$stateChangeSuccess" if you choose to use angular-ui-routeur
If you want to add the controller name instead the route name simply use the follow and replace 'ctrl' with you controller suffixe:
if (toState && toState.controller && typeof toState.controller !== 'function'){
$rootScope.pageStyle = toState.controller.toLowerCase().replace('ctrl','');
}
Hope it help someone else

Meteor and iron-router: dynamically specify a template?

Every example that I have seen with iron-router specifies the template name with a string. Is it possible to do this with a variable? Suppose you have several routes that all use the same dynamic path, and the same data function, but they all need different templates. Is there a way to do this without specifying a different route for every template (which would also mean changing the path I use)?
You can programmatically specify things like the template and the layout with a custom action function. The example below demonstrates showing a particular template if the required document is found based on an id in the route. You can use the same semantics for both routes and controllers.
var postsController = RouteController.extend({
waitOn: function() {
return Meteor.subscribe('post', this.params._id);
},
action: function() {
if (Posts.findOne(this.params._id)) {
this.layout('postsLayout');
this.render('posts');
} else {
this.render('notFound');
}
}
});
Once 0.8.2 is released it should be trivial to do with UI.dynamic even without Iron-Router: https://github.com/meteor/meteor/issues/2123.

How to use YUI compressor in Symfony2 routing/controller

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.

What is the best way to translate JavaScript literal strings in Assetic assets?

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.

Resources