Plantillas literales en ES6

facebook-svg gplus-svg twitter-svg

En JavaScript podemos crear un cadena de texto ( string ) utilizando "comillas dobles" o 'sencillas'. Desde hace poco, en ES6, también podemos utilizar `comillas invertidas` ( backticks ) con este propósito. Y la verdad es que estas invertidas son mucho más útiles.

Cadenas de texto con salto de línea

Hasta ahora no era posible introducir un salto de línea en una cadena de texto sin que todo se venga abajo. Esto ya no pasa si utilizamos comillas invertidas.


const descripcion = `Este libro es un manual de referencia para el programador,
                     con capítulos que explican todo lo que necesita saber 
                     para obtener el máximo partido de JavaScript.`;

Pero hay más: las comillas invertidas nos permiten crear plantillas utilizando variables en la cadena de texto. Hasta ahora la única solución era concatenar variables de esta manera:


const titulo = "La Guía Definitiva.";
const autor = "David Flanagan";
console.log("JavaScript. " + titulo + " Un libro escrito por " + autor + ".");

Ahora lo podemos hacer utilizando el símbolo dólar y poniendo el nombre de la variable entre llaves: ${variable}

console.log(`JavaScript. ${titulo} Un libro escrito por ${autor}.`);

También es posible hacer operaciones aritméticas entre las llaves:

const precio = 20.5;
const unidades = 3;
console.log(`El importe a pagar es ${precio * unidades} Euro`);

Crear plantillas HTML

Una aplicación práctica de todo esto sería crear fragmentos de HTML, como por ejemplo descripciones de productos.

See the Pen ES6 Plantillas literales by Gabi (@enxaneta) on CodePen.

En el siguiente ejemplo tenemos un objeto oLibro que contiene la información acerca de un libro .


const oLibro = {
  titulo :       "JavaScript Ninja",
  autores :      ["John Resig","Bear Bibeault"],
  isbn :         "8441533970", 
  paginas :      "432",
  descripcion : `Este libro es un manual de referencia para el programador,
                 con capítulos que explican todo lo que necesita saber 
                 para obtener el máximo partido de JavaScript.`,
  precio :       "44.65"
  }

A continuación utilizamos este objeto para crear una plantilla, un fragmento HTML muy parecido a este:


<div class="libro">
	<h4>JavaScript Ninja<br>
	<small>autores: John Resig y Bear Bibeault</small></h4>
	<p>ISBN-10: 8441533970<br>
	   432 páginas<br>
	   Envío GRATIS disponible
	</p>
	<p>Este libro es un manual de referencia para el programador, con capítulos que explican todo lo que necesita saber para obtener el máximo partido de JavaScript.	</p>
	<h5>44.65 EUR</h5>
</div>

El Javascript para crear la plantilla tiene este aspecto:

const plantillaLibro =   
  `<div class="libro">
   <h4>${oLibro.titulo}<br>
    <small>autores: ${ oLibro.autores[0] } y ${ oLibro.autores[1] }</small></h4>
    <p>ISBN-10: ${ oLibro.isbn }<br> 
       ${ oLibro.paginas } páginas<br>
       Envío GRATIS disponible
    </p>
    <p>${ oLibro.descripcion }</p>
    <h5>${ oLibro.precio } EUR</h5>
   </div>`;
document.body.innerHTML = plantillaLibro;

Lo bonito de todo esto es que podemos dar formato al código, y podemos ajustar el sangrado de código exactamente como lo hacemos en HTML.

Iterar sobre arrays

En el ejemplo anterior el libro tiene dos autores. Pero ¿que pasa si el libro tiene tres autores o cuatro? La buena noticia es que podemos anidar plantillas una dentro de otra ( ${ . . . . . ${. . .}. . .} ) y también podemos iterar sobre arrays, por ejemplo utilizando el método map().

${oLibro.autores.map(autor => ` <span>${autor}</span>`) }

La traducción del código es: para cada autor del array de autores ( oLibro.autores ) pon el autor dentro de un elemento <span>. Pero lo más interesante de todo esto es que podemos utilizar una variable para construir otra variable ( ${ . . . . . ${. . .}. . .} )

Aquí he optado por poner cada autor dentro de un elemento <span>; pero de la misma manera los podemos poner dentro de un elemento <a> o cualquier otro elemento.

Observación: El método map() añade por defecto una coma entre los ítems. Si queremos que esto no pase, o si queremos utilizar otro separador, podemos utilizar el método join():

${oLibro.autores.map(autor => ` <span>${autor}</span>`).join(' y ') }

const plantillaLibro =     
  `<div class="libro">
   <h4>${oLibro.titulo}<br>
   <small>autores: ${oLibro.autores.map(autor => ` <span>${autor}</span>`) .join(' y ') }</small></h4>
    <p>ISBN-10: ${oLibro.isbn}<br> 
       ${oLibro.paginas} páginas<br>
       Envío GRATIS disponible
    </p>
    <p>${oLibro.descripcion}</p>
    <h5>${oLibro.precio} EUR</h5>
   </div>`;
document.body.innerHTML = plantillaLibro;

Utilizar condicionales

Pero ¿que pasa si el libro tiene un solo autor?
También podemos utilizar condicionales dentro de las cadenas de plantilla, y esto puede ser muy útil en este caso.
Necesito saber si hay un solo autor o varios autores. Si hay más de un autor hay que escribir `autores` ; de lo contrario hay que escribir `autor`.

${oLibro.autores.length > 1 ? `autores` : `autor`}:

const plantillaLibro =  
  `<div class="libro">
   <h4>${oLibro.titulo}<br>
    <small>
    ${oLibro.autores.length > 1 ? `autores` : `autor`}:
    ${oLibro.autores.map(autor => ` <span>${autor}</span>`).join(' y ')}</small></h4>
    <p>ISBN-10: ${oLibro.isbn}<br> 
       ${oLibro.paginas} páginas<br>
       Envío GRATIS disponible
    </p>
    <p>${oLibro.descripcion}</p>
    <h5>${oLibro.precio} EUR</h5>
   </div>`;
document.body.innerHTML = plantillaLibro;

Utilizar funciones

Este es un caso fácil, pero las cosas pueden complicarse mucho y el código puede resultar muy complicado. Para simplificar el código también podemos utilizar funciones:

function autorAutores(n){
    return (n > 1) ? "autores " : "autor ";
}

const plantillaLibro =   
    `. . . . . . . . 
    ${autorAutores(oLibro.autores.length)}: 
    . . . . . . . . 

function autorAutores(n){
  return (n > 1) ? "autores " : "autor ";
}

const plantillaLibro =   
  `<div class="libro">
   <h4>${oLibro.titulo}<br>
    <small>
    ${autorAutores(oLibro.autores.length)}: 
    ${oLibro.autores.map(autor => ` <span>${autor}</span>`).join(' y ')}</small></h4>
    <p>ISBN-10: ${oLibro.isbn}<br> 
       ${oLibro.paginas} páginas<br>
       Envío GRATIS disponible
    </p>
    <p>${oLibro.descripcion}</p>
    <h5>${oLibro.precio} EUR</h5>
   </div>`;
document.body.innerHTML = plantillaLibro;

Vea estos ejemplos en codepen

See the Pen ES6 Plantillas literales by Gabi (@enxaneta) on CodePen.

Funciones de post procesado

Otra cosa interesante que viene con ES6 es la posibilidad de dar formato a las cadenas de texto utilizando funciones de post procesado. La verdad es que esto suena a chino así que mejor veamos un ejemplo:


  const titulo = "La Guía Definitiva.";
  const autor = "David Flanagan";
  const frase = `JavaScript. ${titulo} Un libro escrito por ${autor}.`;

En este caso la const frase está compuesta por el array de las cadenas de texto:

["JavaScript. ", " Un libro escrito por ", "."]

y dos variables:

var1: "La Guía Definitiva."
var2: "David Flanagan"

La idea es esta: creamos una función que toma como argumentos el array de las cadenas de texto y las dos variables y después ponemos el nombre de la función justo delante de la frase que queremos modificar:

function modificaLaFrase(cadenas, var1,var2){
  // la función devuelve la frase modificada
  }
  const frase = modificaLaFrase `JavaScript. ${titulo} Un libro escrito por ${autor}.`;

Veamos cómo va:
En este caso voy a crear una función que toma como argumentos las tres cadenas de texto y las dos variables y crea con ellas un fragmento HTML que devuelve con return. Ulteriormente ponemos el nombre de la función delante de la cadena de texto que queremos modificar, y ya está.


function modificaLaFrase(cadenas, var1,var2){
  return `<p>
  ${cadenas[0]}
  <span>${var1}</span>
  ${cadenas[1]}
  <span>${var2}</span>
  ${cadenas[2]}
  </p>`;
  }
  
  const titulo = "La Guía Definitiva.";
  const autor = "David Flanagan";
  const frase = modificaLaFrase `JavaScript. ${titulo} Un libro escrito por ${autor}.`;

document.body.innerHTML = frase;

Ahora, en el CSS podemos dar formato a la frase:


span {
  color: #00aaaa;
}        

Vea este ejemplo en codepen:

See the Pen ES6 funciones de post procesado* by Gabi (@enxaneta) on CodePen.