No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Custom Elements

7/22
Recursos

Aportes 31

Preguntas 14

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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,wght@0,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.

Excelente curso, llevaba rato buscando este contenido.

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.

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

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!

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! 😄

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 “Hola 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:

Hola buen dia, chicos les queria dar una recomendacion, ya que intente crear mi propio custom element y para crear un titulo use this.title y me generaba error, y busque por 3 horas la solicion y resulto que, el error era debido a que title es una propiedad y/o metodo de HTMLElement y cuando la usaba para mi custom element chicaban ambas y se generaba el error, entonces si les llega a salir un error similar miren que no esten usando el nombre de una palabra reservada, les dejo la linea de codigo para que revisen las propiedades y/o metodos del HTMLElement: console.dir(HTMLElement.prototype);

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 “shadow 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 = “module” 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

En la parte de lllamado de la funcion no me leia el codigo el navegador hasta que le añadi la parte de window. por si les cuesta trabajo que se renderize window.customElements.define("my-element", MyElement);
```js const template = document.createElement('div') template.innerHTML = ` <style> p { color: red; } </style>

Hola todos

texto ejemplo para la clase

` class myElement extends HTMLElement { constructor() { super(); this.p = document.createElement('p'); } connectedCallback() { this.p.textContent = "Hola Mundo" this.appendChild(this.p) this.appendChild(template) } } customElements.define('my-element', myElement) ```const template = document.createElement('div')template.innerHTML = `\<style>p {color: red;}\</style>\

Hola todos\

\

texto ejemplo para la clase\

` class myElement extends HTMLElement {    constructor() {        super();            this.p = document.createElement('p');    }    connectedCallback() {        this.p.textContent = "Hola Mundo"        this.appendChild(this.p)        this.appendChild(template)    }} customElements.define('my-element', myElement)
hola, este fue el codigo que me invente siguiendo esta clase, perdon por el frances, le tire 1hora y ya me empezaba a desesperar que no funcionara y no entender el porqque ```js console.log('why is this shit not working') const element = document.createElement('div'); element.innerHTML=` <style> table{ background-color: aquamarine;} button{background-color: cornflowerblue; } </style>

FUCKING SHIT

<button>O</button> <button>O</button> <button>O</button>
<button>asdf</button> <button></button> <button></button>
` class first extends HTMLElement{ constructor(){ super(); this.table=document.createElement("p") } connectedCallback(){ this.table.textContent="accesible information!!" this.appendChild(element) this.appendChild(this.table) } } customElements.define('o-tag',first); ```
<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

**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? 😄