Fallback en composition - web components
Tags: webcomponents, lit, javascript, webdev
Published: 2022-11-22 01:38:13

La composición es un patrón que nos permite definir en nuestros componentes ciertas partes que serán ocupadas por elementos externos al componente.

Esto hace que nuestros componentes sean más flexibles ya que es más fácil separar responsabilidades, lo que evita crear componentes que encapsulen todo en una sola línea como un sistema de caja negra

En ocasiones necesitamos que el componente cumpla con cierta funcionalidad aunque el usuario no brinde los elementos necesarios para el componente, pero ¿como hacemos eso?. En este punto entran los fallbacks.

Vamos a comenzar por un ejemplo básico, vamos a crear un componente llamado ImageFilter, el cual aplicará ciertos filtros a una imagen.

Para que este elemento funcione necesita una imagen entonces vamos a ello.

```javascript
import { LitElement, css, html } from 'lit';

export class ImageFilter extends LitElement {
  static get properties() {
    return {
      filter: { type: String },
    };
  }

  constructor() {
    super();
    this.filter = 'gray';
  }
  render() {
    return html`
      <div class="filter-${this.filter}">
        <slot></slot>
      </div>
    `;
  }

  static get styles() {
    return css`
      :host {
        min-width: 98%;
        margin: 0 auto;
        padding: 2rem;
        text-align: center;
      }

      .filter-gray {
        filter: grayscale(100%);
      }
    `;
  }
}

window.customElements.define('image-filter', ImageFilter);
```
Como puedes ver es un web component cuya mayor gracia es aplicar un filtro y declarar un slot que nos permite hacer la composición. Puedes ver el código completo [aquí](https://stackblitz.com/edit/vitejs-vite-4mm187?file=index.html)

Ahora para usarlo simplemente usamos las siguientes líneas

```html
<image-filter>
   <img style=" width: 50%;" src="./public/vite.svg" alt="vite logo"/>
</image-filter>
```

Obtendríamos el siguiente resultado

![Vite logo en escala de grises](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddwhznivlgq44ejv10v0.png)

Pero si no tuvieramos una imagen no podriamos ver el efecto aplicado por el componente, entonces necesitamos algo que ocupe el lugar del elemento hijo si es que no esta presente, para ello usaremos un fallback.

Para crear un fallback en nuestro slot simplemente debemos actualizar nuestro método `render` en ImageFilter para agregar contenido al slot.

```javascript
render() {
    return html`
      <div class="filter-${this.filter}">
        <slot>
          <img style="width: 50%" src="./src/assets/lit.svg" alt="Vite logo" />
        </slot>
      </div>
    `;
  }
```
Si al slot no se le brinda contenido externo, el contenido interno tomará su lugar, así funcionan estos fallbacks. Asi que cuando usamos el componente de esta manera

```html
<image-filter></image-filter>
```

Podremos ver el siguiente resultado

![Lit logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rb3gy4zql6l79blup9i0.png)

Espero les haya gustado y les sea útil para muchas cosas, lo he utilizado en componentes más complejos como menús e inputs de búsqueda pero trate de hacer algo simple para mostrar un ejemplo de implementación, recuerden que el código de este ejemplo está [aquí](https://stackblitz.com/edit/vitejs-vite-4mm187?file=index.html)