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 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
Step 2
Step 3
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.
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.
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:
@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:
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?
handleOpen() {
SnackbarState.update((currentSnackbar) => {
return {
...currentSnackbar,
visible: true,
title: 'LinkedIn',
description: 'Amazing, it works fine!',
};
});
}
Demo
References:
https://angular.dev/guide/signals
Top comments (2)
No need to use effect(), just use the signal in the templates.
Thanks Sebastián, I will update the article soon, it makes sense!