7

I have a very specific edge case which I need to use a template literal within a template literal but can't get it done.

The code looks something like this:

<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p> 

However I will have to wrap that in a function, while maintaining the value of the SOMELINK variable, this causes errors to happen. Whether I escape the ticks or not.

someFunction (`<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p>`) 

With escaped ticks I get the following error message:

Error: Expected SOMELINK but none provided

Without, I get:

Unexpected token, expected ","

How do I handle this?

Edit: It should probably be noted that the code being passed in someFunction will be rendered and it need to be used. It will eventually be passed in to another tag through dangerouslySetInnetHTML. So it will look something like this:

<div dangerouslySetInnerHTML={{__html: someFunction(`<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p>`)}}/> 

Not sure if this is relevant, but someFunction just does some modifications on the text.

4

5 Answers 5

4

I think you're overcomplicating it. If you only need to maintain the value of SOMELINK, this should work:

someFunction(`<p>Something something <a href="${SOMELINK}/blah">SomeLink</a></p>`) 
Sign up to request clarification or add additional context in comments.

4 Comments

That will be rendered though. And if I do that, it sends me to the wrong link. Instead of going to where SOMELINK sends me to, it will go to: http://www.myoriginalpage.com/%7B%22http://www.somelinkpage.com/blah%22%7D. Instead of http://www.somelinkpage.com/blah
Seems like that's an issue with your function and that function isn't described in your question.
I didn't think it was relevant, but now thinking about it, it is. That literal passed in the function will be passed in to another tag and I use dangerouslySetInnerHTML to render the content. I'll update the OP to include this in more detail.
Update: I don't know what I did differently from the first time around when I originally replied to your answer. But I tried it a second time and it worked perfectly. Probably my own incompetence. Thanks!
3

Introduction

As imjared says in his answer, you're certainly complicating what a JavaScript template is. But I'd like to make it clearer by explaining the grammar of a template.

There are up to four different parts in a template and you can write a template within a template as I'll show you below, but not quite the way you mentioned it.

Fancy Strings

First of all, a template a nothing more than a fancy way to write a string with expressions defined within. If you type:

typeof `this template` (1) 

in your browser console, it will write "string".

In the old days, when you wanted to concatenate many strings together, you would end up writing:

"string1" + "string2" + ... + "stringN" (2) 

Some of the parameters could be numbers which would then be converted to string automatically (in most cases, it would work as expected). However, if you wanted to compute an expression, you most often had to write that expression between parenthesis:

"string1" + (a + b * c) + "string2" (3) 

Modern JavaScript has Templates

Templates replace that with the ${...} special syntax. Within the ${...}, you can write your expression. This means (3) can be rewritten as follow using the template syntax:

`string1${a + b * c}string2` (4) 

The syntax also has the advantage to look like you can insert a variable within a template like so:

`string1${varname}string2` (5) 

This is still an expression, it just happens to be limited to varname.

As a result, you have four possible different parts in a template:

  1. One String

    If your template is just one string (i.e. no ${...}) then it is just like a string.

    `this is just like a string` (6) 
  2. Two Parts

    If you have one expression within a template, then you have a HEAD and a TAIL in your template. (4) and (5) above are templates with a HEAD and a TAIL.

  3. Three Parts

    If you write a template with more than one expression, that adds one or more special parts in between the expressions. These are called MIDDLE templates.

    `head${expr1}middle${expr2}middle${expr3}tail` (7) 

Templates Inside a Template

As I mentioned above, you can actually write a template inside a template. In most likelihood, you won't need such, but it is possible because what appears between the ${ and } is an expression and a template is viewed a primary literal (more or less, it's a tad bit more complicated than that...)

`string1${v + `sub-template${ sub_sub_template_is_possible }tail` + w}string2` (8) 

As mentioned within the sub-template example in (8), you could have another sub-sub-template within the sub-template. I think that in most cases, you are not likely to need such since the root template already gives you all the necessary functionality.

Escape Characters

Templates, just like strings, support escaping various characters using the backslash as the introducer:

  • \<octal>

  • \x<hexadecimal>

  • \u<hexadecimal>

  • Some special characters such as the character n which represents the newline (\n)

  • Finally, the other characters are escaped as is, this would include:

    \` (9) 

    to escape the template quotes, in which case they are viewed as the quote character, not a template starting or ending point. In other words, string (10) is equal to string (11):

    `\`` (10) "`" (11) 

Very Much Simplified Grammar

Here are the parts mentioned above in simplified BNF-like syntax:

TemplateLiteral ::= Template | TemplateHead TemplateExpression* TemplateTail TemplateExpression ::= Expression | TemplateExpression TemplateMiddle Expression Template ::= '`' Character* '`' TemplateHead ::= '`' Character* '${' TemplateMiddle ::= '}' Character* '${' TemplateTail ::= '}' Character* '`' Character ::= ... -- characters valid in strings, except '${' and '`' (12) 

Reference

The JavaScript language is described in the ECMA-262 document found on this page:

https://www.ecma-international.org/publications-and-standards/standards/ecma-262/

Search for Template Literal Lexical Components. You will find the four parts (and much more) that I mentioned above: Template, TemplateHead, TemplateMiddle, and TemplateTail.

5 Comments

It's worth noting that any ${} expressions that are intended for the inner string should also be escaped: `${}
@DarkRebellion I'm not sure I understand your comment. Would you have an example to clarify? You can escape the $ character if necessary so that way the ${ is not viewed as a template expression. So \${ would appear as ${ in the final string and anything between the { and } is not interpreted as an expression (actually, the } is not even necessary).
I have accidentally typed in `${n} instead of \${n}. I apologize. console.log(` <button onclick = ' let n = 10; alert(\` You have \${n} dollars \`); ' > button </button> `); I was working in a code similiar to this yesterday, and since I had not escaped the $, that meant that n got evaluated together with the outer string instead of with the inner one. Of course, n didn't exist yet, so I got errors. This was fixed by putting /${n} instead of ${n}.
I'm sorry I can't provide a more clear example as I am not allowed to format code inside comments
Oh. Okay. I understand. Yeah, that makes sense. If you generate code that itself makes use of templates. Maybe that's a case where you could use the standard string concatenation operator... (P.S. code that includes a back tick cannot be formatted properly in a comment, indeed.)
2

You can do like:

someFunction(`<p>Something something <a href={${SOMELINK}/blah>SomeLink</a></p>`); 

Comments

1

Try this

someFunction("<p>Something something <a href={"+`${SOMELINK}/blah`+"}>SomeLink</a></p>") 

I think you also need to make the route relative

"<p>Something something <a href={/"+`${SOMELINK}/blah`+"}>SomeLink</a></p>" 

Comments

0

I think that SOMELINK variable is not available in that case. You should provide SOMELINK first.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.