Search code examples
javascriptphprequirejstwigsymfony

Generate JavaScript with Twig on Symfony 3.0 without interfering with {} in JavaScript code


I try to generate a way that I will be able to get the URLs of each AJAX call by using Twig's path function. The reason I am doing that is because I try to create a single-page application by using Knockout MVVM and require.js therefore I need Ajax calls and I need the URLs to be generated dynamically.

The way I do it is that I create a Route:

  /**
  *@Route("/ajax.js",name="ajax_calls")
  */
  public function ajax_calls(Request $request)
  {
    $response=$this->render('javascript/ajax_calls.js.twig');
    $response->headers->set('Content-Type', 'application/javascript');

    return $response;
  }

And I load the specific template (javascript/ajax_calls.js.twig):

/**
*Returns the urls of the calls we need
*/
define([],function($)
{

  return {
    /**
    *Urls for the albums (aka image groups)
    */
    'albums':{
              'get':function()
               {
                return "{{path('user_groups')}}";
               },
               'add':function()
               {
                 return "{{path('group_add')}}";
               }
               'delete':function()
               {
                   return "{{path('group_delete')}}";
               }
               'edit':function()
               {
                 return "{{path('group_update')}}";
               }
              },
    /**
    *Urls for the Images
    */
    'images':{
              'add':function(group_id)
              {
                return "{{path('add_images', group_id='^group_id^')}}".replace("^group_id^",group_id);
              },
              'delete':function()
              {
                return "{{path('delete_images')}}";
              }
             }
  };
});

I use fefine because I want to be able to be loaded with require.js and as you can see I try to generate an Object that returns the URLs for a specific part of an single page application.

But somehow on line:

    'albums':{

There's is a conflict and I do not know how to escape it.

The specific error I get is:

Arguments must be separated by a comma. Unexpected token "punctuation" of value ":" ("punctuation" expected with value ",") in main.js.twig at line 11. 

How can I fix this, or is there an alternative way to get the URLs as a JavaScript object (by generating them dynamically)?

Note: I also seen the https://github.com/FriendsOfSymfony/FOSJsRoutingBundle/blob/master/Resources/doc/index.md as posted on Ajax url parametetr using Twig path

But it does not help me on how I designed the application (I use view models and I want to keep the view models as clear as possible from URLs and load them externally).

Also I will be grad for an alternate way to do that.


Edit 1:

I tried with:

/**
*Returns the urls of the calls we need
*/
define([],function($)
{

  return {
    /**
    *Urls for the albums (aka image groups)
    */
    'albums': {% verbatim %} { {% endverbatim %}
              'get':function()
{% verbatim %}   { {% endverbatim %}
                return "{{path('user_groups')}}";
               },
               'add':function()
               {% verbatim %} { {% endverbatim %}
                 return "{{path('group_add')}}";
               }
               'delete':function()
               {% verbatim %} { {% endverbatim %}
                   return "{{path('group_delete')}}";
               }
               'edit':function()
               {% verbatim %} { {% endverbatim %}
                 return "{{path('group_update')}}";
               }
              },
    /**
    *Urls for the Images
    */
    'images': {% verbatim %} { {% endverbatim %}
              'add':function(group_id)
              {% verbatim %} { {% endverbatim %}
                return "{{path('add_images', group_id='^group_id^')}}".replace("^group_id^",group_id);
              },
              'delete':function()
              {% verbatim %} { {% endverbatim %}
                return "{{path('delete_images')}}";
              }
             }
  };
});

And returns the error:

Arguments must be separated by a comma. Unexpected token "punctuation" of value ":" ("punctuation" expected with value ",") in main.js.twig at line 11. 

Edit2:

I also get the same error with:

{% verbatim %}
/**
*Returns the urls of the calls we need
*/
define([],function($)
{

  return {
    /**
    *Urls for the albums (aka image groups)
    */
    'albums':{
{% endverbatim %}
              'get':function()
               {
                return "{{path('user_groups')}}";
               },
               'add':function()
               {
                 return "{{path('group_add')}}";
               }
               'delete':function()
               {
                   return "{{path('group_delete')}}";
               }
               'edit':function()
               {
                 return "{{path('group_update')}}";
               }
{% verbatim %}
              },
    /**
    *Urls for the Images
    */
    'images':{
{% endverbatim %}
              'add':function(group_id)
              {
                return "{{path('add_images', group_id='^group_id^')}}".replace("^group_id^",group_id);
              },
              'delete':function()
              {
                return "{{path('delete_images')}}";
              }
{% verbatim %}
             }
  };
});
{% endverbatim %}

Edit 3:

I figured out that I generate an another JavaScript file. The controller generates it by using the main.js.twig:

requirejs.config({
  baseUrl:'{{asset('')}}',
  paths:{
    'text':'assets/vendor/js/text.min',

    'knockout':["https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min",'assets/vendor/js/knockout.min'],
    'pager':"{{asset('assets/vendor/js/pager.min')}}",
    'jquery':"{{asset('assets/vendor/js/jquery.min')}}",
    'boostrap':"{{asset('assets/vendor/js/bootstrap.min')}}",

    'ajax':"{{path('ajax_calls')|replace('.js':'')}}",

    {% block Viewmodels %}
    {% endblock %}

    'compMessage':'assets/js/components/message',
    'extBooleanToggle':'assets/js/extenders/booleanToggle',
  },
  shim:{
    'pager':['knockout'],
    'bootstrap':['jquery'],
    },
  waitSeconds: 200,
});

{% block initFunction %}
{% endblock %}

And the problem that generates is the line:

'ajax':"{{path('ajax_calls')|replace('.js':'')}}",

What I try to do in this line is to generate a "fake" .js file without the .js in order to require.js to load it with .js extension.


Solution

  • I changed the line:

    'ajax':"{{path('ajax_calls')|replace('.js':'')}}",
    

    with:

    'ajax':"{{path('ajax_calls')|trim('.js')}}",
    

    On main.js.twig and works like charm!