Creating a Snackbar using Signals and Tailwind CSS generated with V0
Tags: angular, javascript, tutorial
Published: 2024-06-10 13:49:21

Recently I discovered how easy it is to create a component that serves the whole application using signals to manage the state, without needing to include a complex library like NgRx.

For this experiment, I also use the power of V0.dev, which provides an artificial intelligence to create components React or pure HTML with Tailwind CSS.

## Creating the UI using V0
Enter in the [v0.dev](https://v0.dev/) and put a prompt with the idea of the UI you want, in this case, I put:

> A clean snackbar com title, description and a button in the right side

### Step 1
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cd3rszfbumrfayioa46c.png)

### Step 2
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cz1q975e1rtj38mcg92h.png)

### Step 3
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6qfwgwsijtmij9t51a4.png)

That's it, thanks v0 and Tailwind CSS 🥰

## Structure used to organize
You are free to organize your own idea, but in my experience, I use:

### /components
Seems obvious, but this is where I store my components.

### /components/models
The file `snackbar.ts` is used to export the interface used on the component.

``` typescript
export interface SnackbarOptions {
  visible: boolean;
  title?: string;
  description?: string;
}
```

Often when we create a new component with the Angular CLI, we have these files:
- snackbar.component.html
- snackbar.component.ts
- snackbar.component.spec.ts
- snackbar.component.scss

To create the state of the component, I included a new file called `snackbar.state.ts`, which contains the initialization of the signal.

``` typescript
import { signal } from '@angular/core';
import { SnackbarOptions } from './models/snackbar';

export const InitialState: SnackbarOptions = {
  visible: false,
};

export const SnackbarState = signal(InitialState);
```

Now we need to put the template of the component in the place of the application (generally where we have the `<ng-outlet>` if you work with routes), this strategy with Signals is possibly due to the nature of Signal, we can easily listen to the changes of a signal using `effect()` inside the `constructor()`.

In this example, I used the `main.ts` file:

``` typescript
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [SnackbarComponent],
  template: `
    <main>
      @if(snackbar) {
        <snackbar
          [title]="snackbar.title"
          [description]="snackbar.description"
          [visible]="snackbar.visible"
        ></snackbar>
      }
    </main>
  `
})
```

This is where the magic happens, using the special method effect, Angular can identify and update the value of a signal:

``` typescript
export class App {
  snackbar: SnackbarOptions | undefined;

  constructor() {
    effect(() => {
      this.snackbar = SnackbarState();
    });
  }
}
```

To test the Snackbar, we are going to include a method to update the signal, the interest is you are free to update the Snackbar in any place of the application, you should only import the `snackbar.state.ts`, and the Snackbar `effect()` placed in the app will happen, nice isn't it?

``` typescript
handleOpen() {
    SnackbarState.update((currentSnackbar) => {
      return {
        ...currentSnackbar,
        visible: true,
        title: 'LinkedIn',
        description: 'Amazing, it works fine!',
      };
    });
}
```

## Demo
{% embed https://stackblitz.com/edit/signal-snackbar?embed=1&file=src%2Fcomponents%2Fsnackbar.component.html&view=preview %}

References:
[https://angular.dev/guide/signals](https://angular.dev/guide/signals)