Por norma general, los atributos de una etiqueta HTML se utilizan para pasar información desde el exterior a la propia etiqueta HTML. En el caso de los custom elements sirve para exactamente lo mismo. Esta información puede ser de tipo textual
Por ejemplo, observemos el siguiente ejemplo:
<app-element value="15" is-enabled></app-element>
En este caso, el componente tiene 2 atributos:
- El atributo
value
contiene el15
, sin embargo, en HTML los atributos siempre son. - El atributo
is-enabled
no indica ningún valor, técnicamente es unde tamaño 0
, que se considera un.
Atributo vs Propiedad
Antes de continuar, es importante tener claro un concepto que suele complicarse porque los frameworks Javascript lo ocultan y simplifican. Un atributo HTML y una propiedad Javascript pueden tener el mismo valor, pero no tienen necesariamente que ser iguales.
Veamos un ejemplo para comprenderlo bien. En la clase Javascript asignamos un valor a this.name
, por lo que la propiedad name
de la clase AppElement
valdrá ManzDev
:
class AppElement extends HTMLElement {
constructor() {
super();
this.name = "ManzDev";
console.log("✅ Propiedad: ", this.name);
console.log("✅ Atributo: ", this.getAttribute("name"));
}
}
customElements.define("app-element", AppElement);
<p>Mira la consola Javascript para ver el resultado.</p>
<app-element name="Manz"></app-element>
Sin embargo, en la parte del HTML, creamos un elemento HTML <app-element>
con el atributo name
a Manz
. Si pulsamos en la demo y comprobamos la consola Javascript del navegador, veremos que el atributo name
tiene el valor Manz
, mientras que la propiedad name
tiene el valor ManzDev
.
Esto ocurre así porque son conceptos diferentes, sin embargo, en los frameworks Javascript los suelen igualar para hacerlo más sencillo.
Ten en cuenta que existen ciertos atributos especiales, como el
id
, que al establecer dicho atributo, automáticamente se crea su propiedad (y viceversa). No obstante, son excepciones.
Acceder a atributos HTML
Para trabajar con los atributos de un elemento HTML estándar, tenemos los siguientes métodos (los cuales podemos utilizar también para custom elements):
Métodos | Descripción | |
---|---|---|
this.hasAttributes() | Nos indica si el componente tiene algún atributo. | |
this.getAttributeNames() | Devuelve un | |
this.hasAttribute( name) | Nos indica si el atributo name está definido. | |
this.getAttribute( name) | Devuelve el valor del atributo name o |
Algunas consideraciones interesantes:
El método
getAttributeNames()
devuelve un arraycon todos los atributos del elemento. Los strings están siempre en minúsculas (lowercase). El método
.getAttribute()
devuelvecuando no existe el atributo indicado. Si existe pero no tiene valor, devuelve una cadena de texto vacía.
Todos son métodos que permiten comprobar si existen ciertos atributos o el valor que contienen, así que, veamos como utilizar estos métodos en una clase de un WebComponent.
Observa que los ejecutamos en en el interior del método constructor()
y hacemos referencia siempre al this
, que es una referencia al componente en cuestión:
class AppElement extends HTMLElement {
constructor() {
super();
console.log("¿Tiene atributos?: ", this.hasAttributes()); // true
console.log("Número de atributos: ", this.getAttributeNames().length); // 2
console.log("Atributos: ", this.getAttributeNames()); // ["name", "devname"]
console.log("¿Existe name?: ", this.hasAttribute("name")); // true
console.log("Valor de name: ", this.getAttribute("name")); // Manz
console.log("Atributos inexistentes: ", this.getAttribute("uhghae")); // null
}
}
customElements.define("app-element", AppElement);
<p>Mira la consola Javascript para ver el resultado.</p>
<app-element name="Manz" devname="ManzDev"></app-element>
Esto es muy interesante para enviar información desde fuera del componente y reutilizarla dentro del componente de forma abstracta. Por ejemplo, en el siguiente fragmento de código obtenemos el atributo name
con this.getAttribute()
y mediante el operador ??
indicamos un nombre en el caso de que no se añada el atributo al custom element:
const DEFAULT_NAME = "Nombre desconocido";
class AppElement extends HTMLElement {
constructor() {
super();
this.name = this.getAttribute("name") ?? DEFAULT_NAME;
this.innerHTML = /* html */`
<div class="card">
<h1>${this.name}</h1>
</div>
`;
}
}
customElements.define("app-element", AppElement);
<app-element name="ManzDev"></app-element>
<app-element name="MiduDev"></app-element>
<app-element name="MoureDev"></app-element>
<app-element></app-element>
Esta información es guardada en una propiedad del objeto Javascript, concretamente en this.name
. Un poco más abajo, observa que con ${this.name}
añadimos dicha información en el HTML.
Ten mucho cuidado con aceptar información desde fuera del componente, ya que un usuario podría añadir información maliciosa que se terminaría inyectando en el HTML.
Modificación de atributos HTML
Hasta ahora hemos visto como obtener la información que existe en los atributos HTML. Sin embargo, también podemos modificarlos desde el componente. Para ello, podemos utilizar los siguientes métodos:
Métodos | Descripción | |
---|---|---|
this.removeAttribute( name) | Elimina el atributo name . | |
this.setAttribute( name, value) | Añade el atributo name al valor value . | |
this.toggleAttribute( name, force) | Si existe, lo elimina, si no existe, lo añade. |
Algunas consideraciones interesantes:
El método
.setAttribute()
establecerá el atributo con el valor como, aunque se le pasen otros tipos. Si el valor establecido es una cadena vacía, se añade como . El método
.toggleAttribute()
añade un atributo si no existía previamente, o lo elimina si ya existía previamente. Si añadimos el segundo parámetroforce
, simplemente forzaremos a añadir o eliminar el atributo, sin tener en cuenta su estado previo. Este método devuelve si el atributo, tras las operaciones realizadas, existe o no.
En nuestra clase, podemos usar estos métodos para trabajar y modificar estos atributos HTML:
class AppElement extends HTMLElement {
constructor() {
super();
this.setAttribute("name", "ManzDev");
this.innerHTML = /* html */`
<div class="data">
<h1>${this.getAttribute("name")}</h1>
</div>
`;
}
}
En este caso, estamos sobreescribiendo siempre el atributo name
con el valor ManzDev
, por lo que, independientemente de la información que se envíe por atributo HTML, siempre utilizará ManzDev
.
Aquí tienes más información sobre los métodos para gestionar los atributos HTML en el DOM.