👋 ¡Hola Filia! 👋 chicos y chicas. Hoy les hablo de las Signal de Anguar.
✅ Últimamente me he estado actualizando un poco con Angular 17/19, explorando las señales (signals), el nuevo 𝗺𝗼𝗱𝗲𝗹, y todo este mundo moderno de Angular. 🚀 y aunque están en modo solo de desarrollo y no es conveniente aplicarlo en producción son muy interesantes.
✅ Como muchos de nosotros, estoy acostumbrado a usar observables y operadores de RxJS (pipe) para manipular valores o realizar acciones antes de que se dispare un observable.
👉 Entonces, se me ocurrió una idea: 𝗽𝗼𝗿 𝗾𝘂é 𝗻𝗼 𝗵𝗮𝗰𝗲𝗿 𝗹𝗼 𝗺𝗶𝘀𝗺𝗼 𝗰𝗼𝗻 𝘀𝗲ñ𝗮𝗹𝗲𝘀? 🤔
Usando 𝘁𝗼𝗢𝗯𝘀𝗲𝗿𝘃𝗮𝗯𝗹𝗲 (que convierte una señal en un observable), creé una función llamada: 𝘀𝗶𝗴𝗻𝗮𝗹𝗣𝗶𝗽𝗲𝗥𝘅𝗷𝘀 que permite aplicar operadores de RxJS como debounceTime, distinctUntilChanged, map, tap, etc. directamente a una señal. ¡Es como tener lo mejor de ambos mundos! 🌟
📌 Les quise mostrar una de las nuevas características de Angular moderno que es el 𝗺𝗼𝗱𝗲𝗹.
Esta directiva (entrada/salida) es increíblemente útil para comunicar componentes padres e hijos de manera bidireccional.
Combiné model con señales para crear un flujo interactivo y reactivo. 💡
Función signalPipeRxjs
import { Signal } from '@angular/core';
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
import { OperatorFunction } from 'rxjs';
/**
* Transforma una señal usando operadores de RxJS.
*
* Esta función toma una señal de Angular (`Signal`) y aplica un operadores de RxJS
* (como `debounceTime`, `distinctUntilChanged`, etc.) para transformar su valor.
* Luego, devuelve una nueva señal que refleja el resultado de la transformación.
*
* @param source La señal original que se desea transformar.
* @param initialValueOrOperator Un valor inicial opcional o un operador de RxJS que
* se aplicará a la señal.
* Si se proporciona un operador, debe ser del tipo `OperatorFunction<[A], R>`,
* donde `A` es el tipo de la señal original y `R` es el tipo del valor transformado.
*
* @returns Una nueva señal (`Signal<R>`) que contiene el valor transformado después
* de aplicar el operador de RxJS.
*
* @example
* // Aplicar debounceTime y distinctUntilChanged a una señal
* const searchSignal = signal('');
* const transformedSignal = signalPipeRxjs(
* searchSignal,
* pipe(
* debounceTime(500),
* distinctUntilChanged()
* )
* );
*
* // Usar la señal transformada en un effect
* effect(() => {
* console.log('Valor transformado:', transformedSignal());
* });
*/
export function signalPipeRxjs<R, A>(
source: Signal<A>,
initialValueOrOperator?: R | OperatorFunction<[A], R>
): Signal<R> {
const obs$ = toObservable(source);
const pipeOperator =
typeof initialValueOrOperator === 'function'
? initialValueOrOperator
: undefined;
const result$ = obs$.pipe(
pipeOperator as unknown as OperatorFunction<any, R>
);
return toSignal(result$) as Signal<R>;
}
Componente hijo con model
@Component({
selector: 'app-search-products',
template: `
<input
[(ngModel)]="searchProduct"
placeholder="Busca un producto"
/>
`,
})
export class SearchProductsComponent {
searchProduct = model.required<string>(); // Señal de entrada/salida
}
Uso en el componente padre
@Component({
selector: 'app-category-filter',
template: `
<app-search-products [(searchProduct)]="searchProduct" />
`,
})
export class CategoryFilterComponent {
readonly searchProduct = signal<string>(''); // Señal para el valor de búsqueda
readonly onSearch = signalPipeRxjs(
this.searchProduct,
pipe(
debounceTime(500), // Debounce de 500ms
distinctUntilChanged(), // Solo emite si el valor es distinto al anterior
map(value => value.toUpperCase()), // Convertir a mayúsculas
tap(value => console.log('Valor transformado:', value)) // Loggear el valor
)
);
constructor() {
effect(() => {
const query = this.onSearch(); // Obtenemos el valor transformado
console.log('Buscando:', query);
// Aquí puedes llamar a un servicio para realizar la búsqueda
});
}
}
📢 Por favor si lo encuentra útill comparte 👍 👍 👍
¿Por qué es útil?
Flexibilidad: Puedes aplicar cualquier operador de RxJS a una señal.
Reactividad: Las señales y model hacen que la comunicación entre componentes sea más intuitiva y eficiente.
Código limpio: La función signalPipeRxjs encapsula la lógica de transformación, haciendo que el código sea más modular y fácil de mantener.
Qué te parece?
Has probado las señales y model en Angular? ¿Qué otros casos de uso se te ocurren para esta función? ¡Comparte tus ideas en los comentarios! 👇
Top comments (0)