"Transferring a JavaScript variable to Twig: A step-by-step guide for this specific scenario

When it comes to loading a CSS file based on the user's selected theme, I encountered an issue while trying to implement this in my Symfony application using Twig templates. The code worked flawlessly on a simple HTML page, but transferring it to a Twig template posed a challenge in passing the CSS route to the JavaScript document.write function.

<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="css/app-' + themeName + '.css">');
        }
        else
        {
            document.write('<link rel="stylesheet" id="theme-style" href="css/app.css">');
        }

Essentially, I wanted to dynamically set the href attribute of the document.write function within Twig like so:

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

Here, the "app-" part remains constant, while "red" varies based on the value assigned to the themeName variable.

In my attempt to achieve this, I tried:

<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>

However, this approach resulted in an error message:

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

The error stemmed from themeName being a JavaScript variable rather than a Twig variable.

This indicates that passing a JavaScript variable to Twig poses challenges due to their server-side and client-side distinctions. Perhaps utilizing Ajax could provide a solution, though I am unsure how to proceed in that direction.

Answer №1

In JavaScript, concatenation is achieved by using the '+' operator

The '~' operator, on the other hand, is used for concatenation in Twig

document.write('<link rel="stylesheet" id="theme-style" href="{{  asset('bundles/activos/css/app-' + themeName + '.css') }} ">');

Answer №2

When passing a JavaScript variable to Twig is not possible, the solution is to retrieve the theme URI using AJAX.

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <link rel="stylesheet" id="theme-style" href="{{ asset('bundles/activos/css/app.css') }}">
    </head>
    <body>

        <script>
            $(function() {
                var themeSettings = (localStorage.getItem('themeSettings')) ? JSON.parse(localStorage.getItem('themeSettings')) 
                                                                            : {};
                var themeName = themeSettings.themeName || '';
                if (themeName) {                    
                    $.ajax({
                        url : "url/to/get/theme_uri.php",
                        type: "POST",
                        data : {
                            'themeName' : themeName,
                        },
                        success: function(data, textStatus, jqXHR)
                        {
                            $('#theme-style').attr('href', data.uri);
                        },
                    });
                }
            });
        </script>
    </body>

<?php
    //... This would be a symfony controller
    public function themeUriAction(Request $request){
        $path = 'bundles/activos/css/app-' . $request->request->get('themeName').'.css';
        return new JsonResponse(array('uri' => $this->container->get('templating.helper.assets')->getUrl($path)));
    }
    //...

If you are aware of all the themes in advance, storing them in an array can eliminate the need for AJAX.

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <link rel="stylesheet" id="theme-style" href="{{ asset('bundles/activos/css/app.css') }}">
    </head>
    <body>

        <script>

            var themes = {
                {% for theme in themes %}
                    '{{ theme }}': '{{ asset('bundles/activos/css/app-'~theme~'.css') }}',
                {% endfor %}
            };

            $(function() {
                var themeSettings = (localStorage.getItem('themeSettings')) ? JSON.parse(localStorage.getItem('themeSettings'))
                                                                            : {};
                var themeName = themeSettings.themeName || '';
                if (themeName in themes) {
                    $('#theme-style').attr('href', themes[themeName]);
                };
            });
        </script>
    </body>
</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble with yarn install? Keep receiving the error message "Other managers are not allowed"?

Recently, I began using the yarn package manager for one of my projects. To get started, I globally installed yarn using sudo npm install yarn -g. However, when attempting to install dependencies with yarn install, I encountered the following message on t ...

Setting up the propTypes for interface in React TypeScript

How can I specify the correct PropTypes for a property that is an interface in TypeScript with PropTypes? Requirements - Implementing both TS and PropTypes. Goal - To have a more precise type definition than PropTypes.any that meets standard eslint an ...

Creating a Next.js application that retrieves mock data and dynamically presents it on the user interface

I've been attempting to retrieve some placeholder data from an API and showcase it on the screen, but unfortunately nothing is appearing. Interestingly, the data does show up in the console, just not on the actual screen. function Shop() { const [pr ...

How can you decode JSON using JavaScript?

Need help with parsing a JSON string using JavaScript. The response looks like this: var data = '{"success":true,"number":2}'; Is there a way to extract the values success and number from this? ...

Activate JavaScript validation

Within each section (displayed as tabs), I have a custom validator. When one tab is active, the other is hidden. To proceed to submission, I need to disable client validation for the inactive tab. I attempt to do this by calling ValidatorEnable(, false); ...

Utilizing AJAX and PHP for seamless communication, retrieve and authenticate HTTPS SSL CERTIFICATE when interacting

Recently, I successfully created a node.js REST server located at . To develop the front-end, I am utilizing a combination of html, javascript, and php. However, when I attempted to implement an SSL certificate on the front-end, a problem arose: An issue ...

Get the contents inside the window.open using Javascript

First and foremost, I want to acknowledge that I understand the likelihood of this failing due to cross-domain restrictions - just seeking confirmation on that. Here's my approach: I have a window that I open using JavaScript. Subsequently, I make an ...

I am facing an issue where my AngularJS code is not executing properly on JSF

I'm trying to clear the text inside a textarea using AngularJS after typing and clicking on a button. Here's the link to the fiddle for reference: http://jsfiddle.net/aman2690/2Ljrp54q/10/ However, I keep encountering the following error messag ...

modifying the href attribute of a tag is determined by the value of window

I'm working on a jQuery snippet that detects the current window's URL and, depending on the href value of the window, changes the href of an anchor tag. Here's what my code looks like so far: (function($) { "use strict"; $(document).re ...

Creating an object using JSON and implementing custom methods in Javascript

When making a $.ajax request to an API, I receive a chunk of JSON data. The JSON looks something like this: var result = { "status": 200, "offset": 5, "limit": 25, "total": 7, "url": "/v2/api/dataset/topten?", "results": [ { "d ...

Tips for safeguarding AJAX or javascript-based web applications

Utilizing AJAX, this function retrieves information about an image in the database with the ID of 219 when a button is clicked. Any visitor to this webpage has the ability to alter the JavaScript code by inspecting the source code. By modifying the code a ...

Display identical text using JavaScript filter

My search filter highlight is currently displaying [object Object] instead of <mark>match values</mark> when replacing the values. This is the code I am using: this.countries.response.filter((val) => { const position = val.value.toLowerCa ...

Arrange containers into a tower?

Currently, I am exploring the concept of stacking boxes. While I have a solid grasp on how to stack them vertically from top to bottom, I find myself puzzled about how to stack them horizontally. Check out my vertical stacking method here See how I a ...

Retrieving information from a virtual document in a 'pre' save hook using Mongoose

Seeking help with utilizing data from a recently created document to update a value using a 'pre' hook. An example of the model being used: ... title: { type: String, required: true }, company: { type: mongoose.Schema.ObjectId, ref: &ap ...

Disappear text gradually while scrolling horizontally

There is a need to create a special block that displays fading text on horizontal scroll. However, the problem is that the block is situated on a non-uniform background, making the usual solution of adding a linear gradient on the sides unsuitable. Click ...

Matching with Regex beyond the limits

Trying to extract a body tag using regex and then replace it with an appended string. However, encountering an issue where the regex is selecting more content than intended. regex: /<body.*[^>]>/i test string: <bla bla ><body class=&apo ...

Can JavaScript be used to create a CSRF token and PHP to check its validity?

For my PHP projects, I have implemented a CSRF token generation system where the token is stored in the session and then compared with the $_POST['token'] request. Now, I need to replicate this functionality for GitHub Pages. While I have found a ...

"Unique AJAX feature for manual, customized one-time payment subscriptions for adding items to cart

Hello, I am currently working on manually ajaxing this process: <a href="/cbg-gummies?add-to-cart=55337&convert_to_sub_55337=0" class="testing"> Add to cart </a> The purpose of this is to add a one-time purchase option ...

Issues with jQuery slide operation

I'm facing an issue with jQuery and I can't figure out where it's coming from. Here is the error message that keeps showing up in the console: Uncaught TypeError: Object [object Object] has no method 'getElement' script_16.js:46Un ...

Enhance your search experience with AJAX-powered search boxes

I need to implement multiple textboxes on my webpage, each with its own search query to retrieve data from the database. While I have successfully implemented this for one textbox, I am facing difficulties getting it to work for two or more textboxes. He ...