How to pass variable from javascript to twig?

5

The following code is for me to load on the page a CSS or another depending on the chosen theme. This code works perfectly on page HTML pure, but when I try to take my application Symfony not found a way to pass the JS %% route CSS with Twig .

var themeSettings = (localStorage.getItem('themeSettings')) ? JSON.parse(localStorage.getItem('themeSettings')) :
            {};
            var themeName = themeSettings.themeName || '';
            if (themeName)
            {
                document.write('<link rel="stylesheet" id="theme-style" href="css/app-' + themeName + '.css">');
            }
            else
            {
                document.write('<link rel="stylesheet" id="theme-style" href="css/app.css">');
            }

In other words, I want the href of the function document.write to be loaded (for example) so with Twig this would be:

<link href="{{ asset('bundles/activos/css/app-red.css') }} "rel="stylesheet" >

Where app- is fixed and what varies is the word red according to the value of variable themeName

For this I have tried the following but it does not work in this way:

 <script>
        var themeSettings = (localStorage.getItem('themeSettings')) ? JSON.parse(localStorage.getItem('themeSettings')) :
        {};
        var themeName = themeSettings.themeName || '';
        if (themeName)
        {
        document.write('<link rel="stylesheet" id="theme-style" href="{{  asset('bundles/activos/css/app-' ~ themeName ~ '.css') }} ">');
        }
        else
        {
        document.write('<link rel="stylesheet" id="theme-style" href="{{  asset('bundles/activos/css/app.css') }} ">');
        }
    </script>

This throws me this error:

  

Variable "themeName" does not exist in :: base.html.twig at line 1188

Then I tried to do this:

<script>
        var themeSettings = (localStorage.getItem('themeSettings')) ? JSON.parse(localStorage.getItem('themeSettings')) :
        {};
        var themeName = themeSettings.themeName || '';
        if (themeName)
        {
            var cadenacss = "asset('bundles/activos/css/app-')" ~ themeName ~ '.css">';
                {% set cadena=cadenacss %} 
                   document.write('<link rel="stylesheet" id="theme-style" href="{{ cadena }}">');
        }
        else
        {
        document.write('<link rel="stylesheet" id="theme-style" href="{{  asset('bundles/activos/css/app.css') }} ">');
        }
    </script>

And it does not work either, it shows me the following error:

  

Variable "stringcss" does not exist in :: base.html.twig at line 1189

I can not find a way to do this by passing the variable from JS to Twig. First I would like to know if there is any way to pass variables from JS to Twig, but if it can not be done, then I would like to know some other way that I can resolve this.

    
asked by Adriana Hernández 05.08.2016 в 17:34
source

3 answers

3

Because I know all the possible values that the variable themeName can take, I realized that I could solve this in a very simple way. Although with this variant I am not passing any variable from Javascript to Twig , so I am not answering the title of the question, but I do give a solution to the problem raised.

<script>
   var themeSettings = (localStorage.getItem('themeSettings')) ? JSON.parse(localStorage.getItem('themeSettings')) :
   {};
   var themeName = themeSettings.themeName || '';
   if (themeName)
   {
            if (themeName === "blue")
                {
                     document.write('<link href="{{ asset('bundles/activos/css/app-orange.css') }}" rel="stylesheet" >');
                }
            if (themeName === "custom")
                {
                     document.write('<link href="{{ asset('bundles/activos/css/app-custom.css') }}" rel="stylesheet" >');
                }
            if (themeName === "green")
                {
                     document.write('<link href="{{ asset('bundles/activos/css/app-green.css') }}" rel="stylesheet" >');
                }
            if (themeName === "orange")
                {
                     document.write('<link href="{{ asset('bundles/activos/css/app-orange.css') }}" rel="stylesheet" >');
                }
            if (themeName === "purple")
                {
                     document.write('<link href="{{ asset('bundles/activos/css/app-purple.css') }}" rel="stylesheet" >');
                }
            if (themeName === "red")
                {
                     document.write('<link href="{{ asset('bundles/activos/css/app-red.css') }}" rel="stylesheet" >');
                }
            if (themeName === "seagreen")
                {
                     document.write('<link href="{{ asset('bundles/activos/css/app-seagreen.css') }}" rel="stylesheet" >');
                }
  }
    else{
         document.write('<link href="{{ asset('bundles/activos/css/app.css') }}" rel="stylesheet" >');
  }

  </script>

With this I could solve it although I still do not know how it could be done in the other way, that is, passing the variable themeName to Controller and then return it to Twig ; for the case in which you do not know the possible values that this variable can take.

    
answered by 15.08.2016 / 15:45
source
2

You could store the variable that the subject gives you in a cookie, from the controller you can do it, and then with JavaScript you verify that the cookie exists and you get the stored value; in case of not existing then you establish a default theme.

Practical example of implementation

In the application entry controller:

public function indexAction(Request $request){
   $miVariable = algo de la base de datos por ejemplo
   $vista = $this->renderView('AppBundle:Default:index.html.twig', array('varible'=$mivaraible));

   $response = new Response($vista);

    $cookieFromRequest = $request->cookies;
    if (!$cookiesFromRequest->has('myAppTheme'))
    {
        $cookieTheme = new \Symfony\Component\HttpFoundation\Cookie("myApptheme", "defaultTheme");
        $response->headers->setCookie($cookieTheme);
    }

    return $response;
}

And in the JavaScript (adapting it to the current exercise and to speed it up) using the jQuery.cookie pluggin, try to get the cookie with name myApptheme:

var theme = $.cookie('myApptheme');
if(theme !== null)
{
   document.write('<link rel="stylesheet" id="theme-style" href="css/app-' + theme + '.css">');
}
else
{
   document.write('<link rel="stylesheet" id="theme-style" href="css/app.css">');
}


I consider that another solution would be to store the selected topic by the user in the database (if you use a database) and, from the JavaScript, obtain that value via AJAX (you can use the bundle FOSJsRoutingBundle to call the controller from the JavaScript).

And a third solution, since doing everything from javascript: try to get a cookie that contains the theme, if it does not exist, create it with the default theme and the consequent style tag for it. And let's say that when the user selects a topic from the proposed ones, write his name in the cookie to use it in other requests.

    
answered by 02.10.2016 в 01:45
1

You must place directly in your template:

 <link href="{{ asset('bundles/activos/css/app-' ~ themeName ~ '.css') }} "rel="stylesheet" >

And in your controller you must pass that parameter

return $this->render('index.html.twig', array(
    'template' => $template
));

For this case you do not need AJAX, you only need ajax if you want to do the inverse, pass parameters from Javascript to Symphony

    
answered by 06.08.2016 в 04:29