No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Custom Elements

7/22
Recursos

Aportes 27

Preguntas 13

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Solo para refrescar:
.

  • document.createElement: Crea una nueva etiqueta en memoria
  • element.setAttribute: Establece un atributo a alguna etiqueta
  • element.getAttribute: Obtiene el atributo de una etiqueta
  • element.textContent: Establece el contenido en texto de una etiqueta
  • element.innerHTML: Establece el contenido HTML de una etiqueta
  • element.appendChild: Inserta esa etiqueta que estaba en memoria al DOM real

.
Tambi茅n recordemos que no es buna pr谩ctica usar innerHTML 馃憖

Dejo un componente que hice para practicar que consiste en una tarjeta b谩sica =D

const template = `
    <div class="card">
        <h2 class="title">New Card</h2>
        <p class="description">This is an example of a card description made for the Web Component Course from Platzi</p>
        <small class="author">made by @nazarenoalt</small>
    </div>

    <style>
    @import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,[email protected],400;1,700&display=swap');
    * {
        font-family: 'Open Sans', Arial, Helvetica, sans-serif;
        margin: 0;
        padding: 0;
    }
    .card {
        width: 200px;
        margin: 20px;
        padding: 20px;
        border-radius: 7px;
        box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3);
    }
    .title {
        margin: 10px 0;
    }
    .description {
        margin-bottom: 10px;
        color: rgb(134, 134, 134);
    }
    </style>
`

class cardElement extends HTMLElement {
    constructor() {
        super();
    }
    connectedCallback() {
        document.body.innerHTML = template;
    }
}

customElements.define('card-element', cardElement);

MUY recomendable tomar el curso de manipulacion del DOM. Por favor no seguir si no lo tomaste.

Hola:

Tengo una duda.

Porque si en el minuto 13:38, aparecen 3 etiquetas de Hola mundo!!, en el minuto 13:42, no aparecen 3 veces:
hola Mundo!!
Hola mundo 2!
texto ejemplo para la case!

hola Mundo!!
Hola mundo 2!
texto ejemplo para la case!

hola Mundo!!
Hola mundo 2!
texto ejemplo para la case!

Saludos 馃槂

pd. Puse este item aqu铆 ya que en preguntas no me dejo poner mucho texto.

Excelente curso, llevaba rato buscando este contenido.

por ah铆 me encontr茅 con esto espero les ayude

Tremendo, en mi caso que no me quiero atar a ninguna tecnolog铆a, es perfecto! 鈾

Dejo el c贸digo con comentarios y Este tutorial para insertar Web Components a cualquier app:

<!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>
  <my-element></my-element> <!!---Esto viene de JS en customElements.define()-->
  <script type="module" src="my-element.js"></script>
</body>
</html>
const template = document.createElement('div');
template.innerHTML = `
<style>
  .texto{
    color: red;
  }
  p{
    color: blue;
  }
</style>
  <p class="texto">Hola mundo 2 ;)</p>
  <p>Texto ejemplo para la clase</p>
`;

class myElement extends HTMLElement {
  constructor(){
    super(); //* Obtenemos acceso a todos los elementos y m茅todos de la clase que extendemos (heredamos)

    //*Aqu铆 solo estamos creando la etiqueta p, pero a煤n no la veremos en el DOM
    this.p = document.createElement('p'); //*Est谩 lista y cargada en memoria
  }

  //*Esto es lo que agregar谩 cosas al DOM
  connectedCallback(){
    this.p.textContent = "Hola mundo con vanilla JS";
    this.append(this.p); //* Aqu铆 lo agregamos :D
    this.append(template); //*Agregamos al DOM el template que creamos al inicio y tendr谩 los estilos que definimos
  }
}

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

Los nombres de las clases deben estar en PascalCase!

Me encanto esta clase. Me siento como un nene con su nuevo jueguete

Hola, comunidad. Me surgi贸 la misma duda que se aborda en este hilo de comentarios, pero decid铆 crear un hilo distinto para que se vea mejor visualmente.
.
Al seguir los pasos de la clase, se desarrolla el siguiente c贸digo:

.

.

Y se obtiene el siguiente resultado:

.

.


.

Mi duda en ese momento fue: si se est谩 haciendo appendChild de template en cada instancia, 驴por qu茅 s贸lo se ve en la 煤ltima?
.
Reflexion茅, teste茅 y llegu茅 a esta conclusi贸n: template es un objeto de JavaScript; por lo tanto, en memoria s贸lo existe la referencia a un elemento HTML. (Para ver recursos sobre referencia vs. valor en JavaScript ver el final de este comentario).

.

Lo que sucede es que se crea un nodo y su referencia se almacena en la variable template y, como s贸lo existe un nodo, al hacer appendChild en cada instancia, ese mismo nodo se le a帽ade; pero se remueve cuando otra instancia le hace appendChild. Por eso s贸lo queda en el 煤ltimo <my-element>.

.

Si se quisiera que cada instancia de <my-element> tenga un nodo como template, 茅ste debe agregarse al constructor, tal como fue el caso de this.p. De esta manera, se crea un this.template en cada instancia.

.

Resulta de la siguiente manera:

.

.

.

P. D.: Si est谩s de acuerdo en que m谩s estudiantes vean esto, dale like para que este comentario llegue m谩s arriba.
.
P. D. 2: Este comentario respecto a que los estilos definidos en el componente afectan lo que est谩 afuera de 茅l tambi茅n me pareci贸 muy interesante. Les recomiendo que le echen un ojo.

.

Recurso para aprender sobre referencia vs. valor en memoria en JavaScript: Video 1 & Video 2.

La creaci贸n de mi primer Web Component me gust贸 mucho. Esta clase ha sido incre铆ble.

Les comparto el codigo de la creacion de su propio web component! 馃槃

En un video anterior se mencionaba que los Web Components tienen un encapsulado perfecto, pero al menos este ejemplo parece que no lo es, pues los estilos definidos en el componente afectan lo que esta afuera de 茅l.

Supongo que es un tema que se tocar谩 m谩s adelante, xq incluso Diego menciona algo llamado 鈥渟hadow DOM鈥 que creo tenia que ver con eso, pero es bueno saber que no los Web Components no son inherentemente bien encapsulados y pueden afectar al resto de la pagina donde se usan.

hola esto tambien funciona sin necesidad de colocar el atributo type = 鈥渕odule鈥 a nuestra etiqueta script. saludos

MY NOTES FOR CUSTOM ELEMENTS

HTML
.

<!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>Document</title>
</head>
<body>
 
  <my-element></my-element>
  <script type="module" src="./my-elements.js"></script>
  
</body>
</html>

.
JS

//Otra forma de crear etiquetas html
const template =  document.createElement('div');
template.innerHTML = `
<style>
  p{

    color:blue;
  }

  .texto{
    color:red;
  }

</style>
<p class="texto">Hola mundo 2!! <p>
<p>texto ejemplo para la clase</p>
`;


//Inicalizamos nuestra clase y heredamos las propiedades de HTMLElement

class myElement extends HTMLElement{
  //En el constructor estamos inicializando todo lo que se va a guardar en memoria 
    //Para que despues podamos agregarlos como nodos al dom
  constructor(){
    //Como estamos heredando de una clase utilizamos el super para heredar
      //El constructor de esa clase de la que heredamos
    super();

    this.p = document.createElement('p');

    
  }

  //Para poder utilizar mi etiqueta p utilizamos connectedCallback
    //Tiene que escribir asi tal cual
  connectedCallback(){
    this.p.textContent = "Hola mundo!!";
    this.appendChild(this.p);
    this.appendChild(template);


  }

}
//Para definir nuestra clase como etiqueta hacemos lo siguiente
  //El define nos ayuda a definir el nombre de la etiqueta que utilizaremos
    //Define recibe dos parametros  el primero es el nombre de nuestra etiqueta
      //El segundo es el nombre de la clase

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

Les dejo el link de MDN que habla de los custom elemets, esta muy buena la explicaci贸n pero sobre todo explica porque se usa la funci贸n de customElements.define()
https://developer.mozilla.org

<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">
    <script type="module" src="./my-element.js"></script>
    <script type="module" src="./my-column.js"></script>
    <title>Document</title>   
    
</head>
<body>
    
    <!-- <my-element></my-element> -->

    <my-column id="col1"></my-column>
    
    
</body>
</html>

los estilos css los he agregado con el template

let styleColumn  = document.createElement('div');
styleColumn.innerHTML =  
`<style>
    .columna{
        display: flex;
        flex-direction: column;
        width: 100px;
    }
    .inputClass{
        
        background-color: red;
        color: white;
    }
</style>`;

class myColumn extends HTMLElement{
    constructor(){
        super();
        let classOfInput = 'inputClass';
        let colNumber = 1;
        let nCells = 10
        this.arrInputs =[];
        this.colContainer = document.createElement('div');
        this.colContainer.classList.add('columna')
        for(let i = 0; i< nCells ; i++){
            let input = document.createElement('input');
            input.setAttribute('class' , classOfInput);
            input.setAttribute('type' , 'number');
            input.setAttribute('id' , `idCol${colNumber}row${i}`);
            this.arrInputs.push(input);
        }
    }//constructor end.

    connectedCallback(){    
        
        // this.colContainer.appendChild(input)
        this.arrInputs.map(Element => {this.colContainer.appendChild(Element)});
        console.log(this.arrInputs);
        this.appendChild(this.colContainer);
        this.appendChild(styleColumn);
    }
}


customElements.define('my-column' , myColumn);

Esto es una maravilla! Por qu茅 no me hab铆a enterado de los web components antes

Custom Elements

Vamos a crear nuestro primer Web Component 馃槃

Creando el componente

En vs-code creamos un archivo HTML y JS :

Despu茅s de crear nuestra estructura b谩sica de HTML vamos a nuestro archivo de JavaScript y crearemos una clase que ser谩 nuestro componente:

class MyElement extends HTMLElement {
  constructor ( ) {
		// Heredamos las propiedades de HTML element con "super()"
    super();
  }
}

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

Para crear un componente primero debemos crear una clase que extienda a lago llamado el HTMLElement, el cual nos va a permitir definir nuestro componente web.

Para convertir nuestro componente en una etiqueta HTML debemos usar el m茅todo estatico de customElements llamado define( ), el cual recibe dos par谩metros, el primero el nombre de como se llamar谩 la etiqueta de nuestro componente, y el segundo la clase que utilizaremos para definir los comportamientos de nuestro componente .

En este punto ya generamos nuestra etiqueta, y podemos usarla en el HTML:

<!DOCTYPE html>
<html lang="es">
<head>
  ...
</head>
<body>
  **<my-element></my-element>**

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

L贸gica de nuestro componente

Ahora vamos a empezar a definir los comportamientos de nuestro componente:

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

    // Creamos una etiqueta p
    this.p = document.createElement('p');
  }

  // Creamos el m茅todo de conenxi贸n
  connectedCallback() {
    // Introducimos texto a nuestra etiqueta
    this.p.textContent = 'Hola mundo';
    // Agregamos esta etiqueta como hijo de <my-element> 
    this.appendChild(this.p)
  }
}

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

Si vemos nuestro archivo en el navegador podremos ver ya nuestro 鈥淗ola mundo鈥.

Complejidad de componente

Podemos a帽adir muchas m谩s cosas a nuestro componente, tales como estilos y dem谩s, veamos un ejemplo.

// Creamos un div
const template = document.createElement('div');
/* Dentro de este div podemos escribir estilos y dem谩s cosas,
recordemos qu estos estilos no har谩n colici贸n con otros estilos
debido a que los estilos que escribamos aqu铆 solo aplican a nuestro 
componente y NO a otros elementos externos a este
*/
template.innerHTML = `
  <style>
  p {
    color: #9C27B0
  }

  .text {
    font-size: 1rem;
    color: #212121;
  }

  </style>

  <p>Hola mundo 2</p>
  <p class="text">Texto de ejemplo</p>
`

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

    this.p = document.createElement('p');
  }

  connectedCallback() {
    this.p.textContent = 'Hola mundo';
    this.appendChild(this.p);
    // A帽adimos nuestro template a nuestro componente como hijo
    this.appendChild(template)
  }
}

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

Y si todo esta correcto ,veremos nuestro componente en el navegador con todo lo que definimos:

**Snippet **para utilizar web-components en vscode.

{
  "webComponent": {
    "prefix": "webComponent",
    "body": [
      "class $1 extends HTMLElement {",
      "  constructor() {",
      "    super();",
      "    this.attachShadow({ mode: \"open\" });",
      "  }",
      "",
      "  static get styles() {",
      "    return /* css */`",
      "      :host {",
      "        $4",
      "      }",
      "    `;",
      "  }",
      "",
      "  connectedCallback() {",
      "    this.render();",
      "  }",
      "",
      "  render() {",
      "    this.shadowRoot.innerHTML = /* html */`",
      "    <style>${$1.styles}</style>",
      "    <div class=\"container\">",
      "      $3",
      "    </div>`;",
      "  }",
      "}",
      "",
      "customElements.define(\"$2\", $1);",
      "",
    ],
    "description": "Crear un WebComponent nativo (JS Vanilla)"
  }
}

Jugando con lo aprendido en clase logr茅 hacer lo siguiente, no es mucho pero es trabajo honesto jaja, est谩 sin estilos ya que solo me enfoqu茅 en asignar los valores del innerHTML desde afuera de la clase. Adicionalmente a帽ad铆 una funci贸n que muestra la hora del sistema.

const setTitle = () => `Titulo`;
const setDescription = () => `Descripci贸n del item`;

class myElement extends HTMLElement {
  constructor() {
    super();
    this.container = document.createElement("div");
    this.titleText = document.createElement("h1");
    this.setDescription = document.createElement("p");
    this.postTime = document.createElement("p");
  }

  connectedCallback() {
    this.titleText.innerHTML = setTitle();
    this.setDescription.innerHTML = setDescription();
    this.postTime.innerHTML = myFunction();
    this.container.append(this.titleText, this.setDescription, this.postTime);
    this.appendChild(this.container);
  }
}

function myFunction() {
  let date = new Date();
  let hour = date.getHours();
  let minute = date.getMinutes();
  return `${hour}:${minute}`;
}

customElements.define("my-element", myElement);
const template = document.createElement('div')
template.innerHTML = `
    <style>
        p {
            background-color: gray;
        }
    </style>
    <p>Hello world!!</p>
    <p>Hello world 2!!</p>
`

class Element extends HTMLElement {
    constructor(){
        super();
        this.h1 = document.createElement('h1');
    }
    connectedCallback() {
        this.h1.textContent = 'Hello World'
        this.appendChild(this.h1)
        this.appendChild(template)
    }
}

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

,

super https://www.w3schools.com/jsref/jsref_class_super.asp

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  present() {
    return 'I have a ' + this.carname;
  }
}

class Model extends Car {
  constructor(brand, mod) {
    super(brand);
    this.model = mod;
  }
  show() {
    return this.present() + ', it is a ' + this.model;
  }
}

mycar = new Model("Ford", "Mustang");
document.getElementById("demo").innerHTML = mycar.show();```

C贸digo HTML

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

C贸digo JS

const template = document.createElement('div')
template.innerHTML = `
<style>
    .texto {color:red;}
    p {color:blue;}
</style>
<p class="texto">Hola mundo 2 !!</p>
<p>Texto ejemplo para la clase !!</p>
`;

class myElement extends HTMLElement {
    constructor() {
        super()
        /*console.log('Hola mundo') */    
        this.p = document.createElement('p')
    }
    connectedCallback(){
        this.p.textContent = 'Hola mundo!!'
        this.appendChild(this.p)
        this.appendChild(template)
    }
}

/* Definir la etiqueta */
/* .define('nombre-de-la-etiqueta', clase) */
customElements.define('my-element', myElement)

min 11:15 Styled-Components? 馃槃