Paul Atréides
Paul Atréides

Reputation: 51

Getting weird error when concatenating template-literals

I am trying to build a javascript script that will right my header to my html page so I don't have to update every one of my pages when I make a change. I learned that template literals can hold html code in variables so I started using that. I am having an error pop up in VS Code when I use ternary operators however. It says that I'm missing a ).

I've check the whole template literal for any missing parenthesis.

var html = `<div id="branding">
    <h1><span class="btop">JoJo</span> <span class="bbottom">Studios</span></h1>
</div>
<nav>
    <ul>
        <li`+(page=="home" ? ` class="current><a href="#">Home</a>"` : `><a href="../">Home</a>`)+`</li>
        <li`+(page=="games" ? ` class="current"` : ``)+`>
            <div class="dropdown">
                <a href=`+(page=="games" ? `"./"` : (page=="home" ? `"games/"` : `"../games/"`)+`>Games</a>
                <div class="dropdown-content">
                    <a href=`+(page=="games" ? `"` : (page=="home" ? `"games/` : `"../games/`)+`jojobananacatch.html">JoJo Banana Catch</a>
                </div>
            </div>
        </li>
        <li`+(page=="play" ? ` class="current"` : ``)+`><a href=`+(page=="home" ? `"play/"` : `"../play/"`)+`>Play</a></li>
        <li`+(page=="videos" ? ` class="current"` : ``)+`><a href=`+(page=="home" ? `"videos/"` : `"../videos/"`)+`>DevLogs & More</a></li>
        <li`+(page=="about" ? ` class="current"` : ``)+`><a href=`+(page=="home" ? `"about/"` : `"../about/"`)+`>About</a></li>
        <li`+(page=="contact" ? ` class="current"` : ``)+`><a href=`+(page=="home" ? `"contact/"` : `"../contact/"`)+`>Contact</a></li>
        <li`+(page=="account" ? ` class="current"` : ``)+`><a href=`+(page=="home" ? `"account/account.php?account_forward=0"` : `"../account/account.php?account_forward=0"`)+`>Account</a></li>
    </ul>
</nav>`;

The output should just be a string that I can insert into the document. Any help would be appreciated.

Upvotes: 2

Views: 2016

Answers (3)

Miroslav Glamuzina
Miroslav Glamuzina

Reputation: 4557

Although this has already been answered, (missing closing round bracket for nested ternary) I feel you may find benefit using string interpolation with template literals. By doing this you may remove all the concatenation inside of your string (which is one of the main advantages of using template literals as opposed to regular strings).

let page = 'play';
let html = `<div id="branding">
    <h1><span class="btop">JoJo</span> <span class="bbottom">Studios</span></h1>
</div>
<nav>
    <ul>
        <li ${(page==="home" ? `class="current><a href="#">Home</a>"` : `><a href="../">Home</a>`)}</li>
        <li ${(page==="games" ? `class="current"` : ``)}>
        <div class="dropdown">
            <a href=${(page==="games" ? `"./"` : (page==="home" ? `"games/"` : `"../games/"`))}>Games</a>
            <div class="dropdown-content">
                <a href=${(page==="games" ? `"` : (page==="home" ? `"games/` : `"../games/`))}jojobananacatch.html">JoJo Banana Catch</a>
            </div>
        </div>
        </li>
        <li ${(page==="play" ? ` class="current"` : ``)}><a href=${(page==="home" ? `"play/"` : `"../play/"`)}>Play</a></li>
        <li ${(page==="videos" ? ` class="current"` : ``)}><a href=${(page==="home" ? `"videos/"` : `"../videos/"`)}>DevLogs & More</a></li>
        <li ${(page==="about" ? ` class="current"` : ``)}><a href=${(page==="home" ? `"about/"` : `"../about/"`)}>About</a></li>
        <li ${(page==="contact" ? ` class="current"` : ``)}><a href=${(page==="home" ? `"contact/"` : `"../contact/"`)}>Contact</a></li>
        <li ${(page==="account" ? ` class="current"` : ``)}><a href=${(page==="home" ? `"account/account.php?account_forward=0"` : `"../account/account.php?account_forward=0"`)}>Account</a></li>
    </ul>
</nav>`;
console.log(html);

Upvotes: 2

Rafael Rocha
Rafael Rocha

Reputation: 518

That's not how template strings work at all in Javascript (ES6 >).

Don't forget that the + won't actually concatenate the result nor have logic expression inside of it. You have to use this ${...} to surround your js expression so that their results are immediately converted to string.

Example

var html = `<li ${page=="home" ? '"class="current><a href="#">Home</a>':'<a href="../">Home</a>'}</li>`;

That's how you would use template string ( inserting logic inside of strings). Consider also extracting the contents that you are returning in the ternary into their own separate variables. Makes for better reading.

Example

const currentPageLink = 'class="current"><a href="#">Home</a>';
const previousPageLink = '<a href="../">Home</a>';

// and then following the example above

const html = `<li ${page==="home" ? currentAnchor: previousPageLink}</li>`;

Hope this was helpful.

Upvotes: 0

6502
6502

Reputation: 114461

The part inside dropdown class is where the problem is, you are using apparently two nested ternary operators but there's only one closed parenthesis.

Change

<a href=`+(page=="games"
           ? `"./"`
           : (page=="home"
              ? `"games/"`
              : `"../games/"`)+`>Games</a>

to

<a href=`+(page=="games"
           ? `"./"`
           : (page=="home"
              ? `"games/"`
              : `"../games/"`))+`>Games</a>

and the same for the second instance.

By the way you can also use directly expressions inside template (that's the whole point of templates).

This is done using the ${...} syntax that is possibly easier to read in some cases than closing and reopening the template. For example:

let s = "World";
console.log(`Hello, ${s+"."}`)

logs Hello, World.

Upvotes: 3

Related Questions