A√ļn no tienes acceso a esta clase

Crea una cuenta y contin√ļa viendo este curso

Template

8/22
Recursos

Aportes 16

Preguntas 6

Ordenar por:

¬ŅQuieres ver m√°s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi√≥n.

Soy yo o el audio desde el minuto 8 falla?

Basicamente la API Template nos permite conectar un web component de forma más profesional y organizada. También nos ayuda a clonar los elementos facilmente (Ya que como lo hicimos en la clase anterior el elemento no se clonaba, sino que se pasaba de etiqueta en etiqueta hasta la ultima en ser renderizada)

La etiqueta <template>

Es una etiqueta que nos sirve como contenedor de código. Todo lo que escribamos adentro de esta etiqueta no se va a renderizar , sino que hay que activarlo mediante Javascript. El profesor sin embargo no muestra cual es dicho proceso y procede a utilizar una forma distinta. En el siguiente enlace vas a ver cómo se activa desde JS:

Escribir y activar el código dentro de la clase

De esta forma estamos armando toda la estructura HTML dentro de Javascript, pero insertandola en la clase y fraccionando el HTML y CSS para m√°s placer.

En este caso, creamos la clase, con su extension y constructor, luego creamos un método que contendrá la estructura HTML (getElement) . Adentro insertamos la variable template que contiene la estructura.

getTemplate() {
        const template = document.createElement('template');
       	template.innerHTML = `
		...(codigo HTML)
	`
}

En otro metodo (getStyles) todo lo que hacemos es retornar un literal string que contiene el código CSS (si queremos podemos contenerla en una variable, eso es a comodidad del programador)

getStyles() {
        return `...(código CSS)`
}

y luego al final del código de getElement la llamamos de esta forma

${this.getStyles()}

Clonar Elementos

Para clonar el código debemos indicar mediante el método cloneNode que se puede clonar. Para eso invocamos el contenido de getTemplate, y lo anidamos a la clase (que luego al ser invocada en el HTML se convierte en la etiqueta misma)

render() { this.appendChild(this.getTemplate().content.cloneNode(true)) }

Y FINALMENTE…

Invocamos el render

connectedCallback() { this.render(); }

Hola:

Si desean ver como se hace la transici√≥n primero pone el color azul y luego cambia al color rojo (minuto 11:50), se podr√≠a cambiar en la pesta√Īa de network la velocidad de carga de la p√°gina:

Saludos ūüėÉ

una simple linea pero poderosa

section>h2{Hola mundo!}+div>p{Soy m√°s texto ejemplo}

Apuntes y código con comentarios:

<h4>Template</h4>

Esto es opcional. Pero si adentro de tu componente van a venir muchos elementos que se conviertan en nodos, lo idal sería ocupar templates.

Recuerda: todo lo que esté dentro de la etiqueta <Template></Template> NO se va a renderizar de inicio.

Es importante que cloneNode(true) tenga el valor de true porque así podrá copiar todos los elementos anidados del HTML.

Podemos meter estilos con JS pero entrar√°n en conclicto con otros estilos, pero para esto usaremos ShadowDOM.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Custom Elements</title>
</head>
<body>

  <template>
    <h2>Hola desde h2 y template</h2>
    <div>
      <p>Soy m√°s texto dentro de template</p>
    </div>
  </template>

  <my-element></my-element> <!!---Esto viene de JS en customElements.define()-->

  <script type="module" src="my-element.js"></script>

</body>
</html>
class myElement extends HTMLElement {
  constructor(){
    super(); //* Obtenemos acceso a todos los elementos y métodos de la clase que extendemos (heredamos)
  }

  getTemplate(){ //*Esto ser√° puro HTML
    const template = document.createElement('template');
    template.innerHTML = `
      <section>
        <h2>Hola gente desde getTemplate()</h2>
        <div>
          <p>Soy un p√°rrafo</p>
        </div>
      </section>
      ${this.getStyles()} //*Aplicamos los estilos
    `;
    return template;
  }

  getStyles(){ //*Esto ser√° puro CSS
    return `
    <style>
      h2{
        color:red;
      }
    </style>
    `;
  }

  render(){
    this.append(this.getTemplate().content.cloneNode(true));
    //*Es importante que `cloneNode(true)` tenga el valor de true porque así podrá copiar todos los elementos anidados del HTML
  }

  //*Esto es lo que agregar√° cosas al DOM
  connectedCallback(){
    this.render();
  }
}

customElements.define('my-element' , myElement); //* Definimos que la clase se va a convertir en una etiqueta

MY NOTES FOR TEMPLATE

Cabe recalcar que el tema de css es algo de especificada y que saben que las líneas de css que son importante son las que se escriben al final, siempre van a ser mas importantes que las que están arriba es como si se sobrescribieran.

class myElement extends HTMLElement{
  
  constructor(){
    super();



    
  }

  //Generamos una funcion en cual tendremos nuestro template html y esta
    //Funcion retornara este template
  getTemplate(){

    const template = document.createElement('template');
    template.innerHTML = `
      <section>

        <h2>Hola mundo!</h2>
        <div>

          <p> Soy text ejemplo<p>
        
        </div>
      
      </section>

  <!-- Para utilizar nuestros estilos de nuestro metodo lo llamamos desde nuestro template html
       para que se agreguen -->    
      ${this.getStyles()}

    `;
    return template
  }
  //Podremos generar otro metodo para poner los estilos, pero esto mas que todo se hace por simples
    //Buenas practicas pero se puede hacer de otras maneras.
  getStyles(){
    return`

      <style>
        h2{

          color:red;
        }
      </style>
    
    `
  }
  //Generamos otro metodo para que el contenido de nuestra etiqueta template se pueda clonar
    //Para poderlo agregar al dom
  render(){

    //Agregamos el elemento al dom por dentro utilzamos la funcion que genera el template
      //y utilizamos el content.clone(true) para clonar el elemento
        //Le ponemos true porque si este fuera false solo tomaria las etiquetas padre y no
          //Todo lo que tienen por dentro las etiquetas

    this.appendChild(this.getTemplate().content.cloneNode(true))

  }

  
  connectedCallback(){
    //Inicializamos en el dom el metodo de render
    this.render();
    


  }

}

customElements.define('my-element', myElement);

Hmmm, no ví exactamente para qué se usó la etiqueta <template> que escribimos en HTML, imagino que se verá en la siguiente clase
.
Por si les interesa, les dejo el código en mi repo (con ligeros cambios de texto xD)
.
Adicion de templates a los WebComponents

para los que no entendieron lo de ‚Äútemplate‚ÄĚ.

lo que pasa es que solo la etiqueta ‚Äútemplate‚ÄĚ tiene la propiedad ‚Äúcontent‚ÄĚ con la que puedes hacer el ‚ÄúcloneNode(true)‚ÄĚ.


this.getTemplate().content.cloneNode(true)

aqu√≠ NO esta clonando de la etiqueta template que creo en el html, esta clonando el innerHTML de la etiqueta ‚Äútemplate‚ÄĚ que cre√≥ con ‚Äúdocument.createElement(‚Äútemplate‚ÄĚ)‚ÄĚ, de hecho si borran la etiqueta template del html ver√°n que no efecta en nada.


const template = document.createElement("template");

a continuaci√≥n lo que hacer es definir un ‚ÄúinnerHTML‚ÄĚ para esa etiqueta ‚Äútemplate‚ÄĚ que cre√≥ en la linea anterior.


const template = document.createElement("template"); // solo la etiqueta template tiene la propiedad "content"
        template.innerHTML = `
            <section>
                <h2>a</h2>
                <div>
                    <p>x</p>
                </div>
            </section>
        `
        return template;

luego en ‚Äúrender()‚ÄĚ sucede la magia, si en render ustedes ponen ‚Äúthis.appendChild(this.getTemplate())‚ÄĚ ver√°n que les aparece una etiquete ‚Äútemplate‚ÄĚ dentro de ‚Äúmy-element‚ÄĚ

js


this.appendChild(this.getTemplate()

html


    <my-element>
        <template></template>
    </my-element>

sin embargo si ponen " this.appendChild(this.getTemplate().content.cloneNode(true))", ver√°n que les aparece solamente lo que definieron en el ‚ÄúinnerHTML‚ÄĚ, tal que:

js


render(){     this.appendChild(this.getTemplate().content.cloneNode(true))
}

html


    <my-element>
        <section>
            <h2>a</h2>
            <div>
                <p>x</p>
            </div>
        </section>
    </my-element>

y esto solo es posible hacerlo con la etiqueta ‚Äútemplate‚ÄĚ ya que dentro de otras etiquetas no existe la propiedad ‚Äúcontent‚ÄĚ

HTML Template

El elemento HTML <template> es un mecanismo para mantener el contenido HTML del lado del cliente que no se renderiza cuando se carga una página, pero que posteriormente puede ser instanciado durante el tiempo de ejecución empleando JavaScript.
„Ö§
Piensa en la plantilla como un fragmento de contenido que está siendo almacenado para un uso posterior en el documento. El analizador procesa el contenido del elemento <template> durante la carga de la página, pero sólo lo hace para asegurar que esos contenidos son válidos; sin embargo, estos contenidos del elemento no se renderizan.
„Ö§
Para lo que nos sirve la etiqueta <template> es justamente para tener una plantilla, que posteriormente utilizaremos para agregarle contenido din√°mico con JavaScript para a√Īadirlas al DOM, la plantilla como tal nunca se mostrar√° en la p√°gina, s√≥lo se mostrar√°n los nodos creados desde JavaScript que la utilizaron como base para ser creados.

<!-- Creamos la plantilla -->
<template id="template-card">
	<figure>
		<img />
		<figcaption></figcaption>
	</figure>
</template>
const $container = document.querySelector(".container"),
  $template = document.getElementById("template-card").content,
  $fragment = document.createDocumentFragment(),
	cardsContent = [
    {
      title: "Tecnología",
      img: "https://placeimg.com/200/200/tech",
    },
    {
      title: "Animales",
      img: "https://placeimg.com/200/200/animals",
    }
  ];
// Por cada imagen que obtenemos de una API (por ejemplo) utilizaremos la plantilla y sólo le agregaremos el contenido
cardsContent.forEach((el) => {
  $template.querySelector("img").setAttribute("src", el.img);
  $template.querySelector("img").setAttribute("alt", el.title);
  $template.querySelector("figcaption").textContent = el.title;
  let $clone = document.importNode($template, true);
  $fragment.appendChild($clone);
});

$container.appendChild($fragment);

La forma de usar los templates es, crear un código base entre las etiquetas <template>, es decir una plantilla.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Template</title>
  </head>
  <body>
    <h2 class="title">Soy un Template</h2>
    <template>
      <div>
      <p>Texto de muestra</p>
      </div>
    </template>
    <script type="module" src="./template.js"></script>
  </body>
</html>

Luego en JavaScript procedes a clonar el código que esta entre las etiquetas <template>, le adicionar lo que requieres y lo renderizas, ejemplo:

const template = document.querySelector('template').content.querySelector('p');
for (let i = 1; i < 10; i++) {
  let clone = template.cloneNode(true);
  clone.textContent = `Ciclo: ${i}`;
  document.body.appendChild(clone);
}

En el explorador se ve así:

Soy un Template
Ciclo: 1
Ciclo: 2
Ciclo: 3
Ciclo: 4
Ciclo: 5
Ciclo: 6
Ciclo: 7
Ciclo: 8
Ciclo: 9

Recomendación

No se si alguien mas a tenido este problema de que se le duplica el codigo o simplemente no se renderiza en lo particular es muy importante al trabajar con los web components
aperturar y cerrar de forma correcta cada etiqueta
<etiqueta></etiqueta> ya que podemos tener algunos inconvenientes al momento de renderizar

Un tip que lei no me acuerdo donde y me gusto es de cambiar el modo del lenguaje a HTML para escribir el template.innerHTML y que las etiquetas las cree de forma automatica

No entendi muy bien su uso.
Pienso que tiene que ver mas con optimizacion entonces ūü§Ē
Al usar <Template> se crea un Document Fragment el cual no se renderiza, aqui entonces podemos usar innerHTML para definir la estructura HTML del template, dicho template (fragment) tiene un atributo de solo lectura que es content, el cual podemos clonar con cloneNode(true), este metodo recibe un parametro booleano que indica si el clonado sera profundo o no. Al clonarlo estamos transformando el string del template a nodos reales (elementos de HTML) que luego podemos insertar al DOM con append.
De esta forma nosotros solo le pasamos un solo Nodo con sus nodos hijos, en lugar de un innerHTML que el navegador tenga que traducir a nodos, lo cual deriva en mas seguridad y optimizacion. No estoy seguro si lo entendí correctamente.

Para que se usa el template ¬Ņ?

Bueno al crear el nodo Template con Js nos sirve para simplemnte tener una base desde donde trabajar, en el ejemplo de la clase Diego genero la semantica dentro de un Section para tener un mejor control semantico y visual. La etiqueta simplente proporciono precisamente esa base para ahi colocar el codigo

class Element extends HTMLElement {
    constructor(){
        super();
    }
    getTemplate() {
        const template = document.createElement('template');
        template.innerHTML = ` 
            <section>
                <h2>Hello Guys</h2>
                <div>
                    <p>Texto de ejemplo</p>
                </div>
            </section>
        `;
        return template;
    }

    render() {
        this.appendChild(this.getTemplate().content.cloneNode(true));
    }

    connectedCallback() {
        this.render();
    }
}

customElements.define("my-element", Element);```

,