Angular 16@next with Signals codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API.
This codebase was created to demonstrate a fully fledged Front-end application built with Angular 16@next w/ Signals including CRUD operations, authentication, routing, pagination, and more.
This is to explore and showcase how Angular 16@next w/ Signals would look like in a project.
For more information on how to this works with other frontends/backends, head over to the RealWorld repo.
This implementation takes on the Extreme Signals approach in order to find a common ground where RxJS and Signals can coexist happily in an Angular project.
I'm forcing myself to go as far as I could without RxJS so please keep that in mind. This implementation is also an open invitation for you to tweak where you think RxJS makes more sense.
Describe the general architecture of your app here
withComponentInputBinding
is also utilized for binding Route data to Routed Components' Inputs (checkfeature-article
)- API calls happen based on User Events/Actions (click something, submit somthing, navigate into a component etc...) rather than Observable Stream
status
(ApiStatus
) signal is a bit of a pain-point and should be abstracted better. Usually when we work with API calls and RxJS, we'd usually have
this.trigger$.pipe(
tap(() => this.loading$.next(true)),
switchMap(() =>
this.service.getData().pipe(
tap({
finalize: () => {
this.loading$.next(false);
},
})
)
)
);
This pattern is a bit awkward with Signals if we want to keep declarative mindset. effect()
(and toObservable()/fromSignal()
internally uses effect()
) doesn't allow
writes to Signals by default. It's tricky to have:
effect(() => {
this.loadin.set(true); // this is not
const sub = this.service.getData().subscribe(() => {
this.loading.set(false); // this is fine
});
});
- Without RxJS, we do forgo some forms of Race Condition handling as well as Cancellation. I'd assume the ecosystem like NgRx, RxAngular, NgXS are going to come up with some abstractions for this. The point is on the consumers' code, we don't need to think about RxJS vs Signals. It depends on the public APIs of these ecosystems.
authGuard
still uses RxJS because I need the Guard to wait for theAuthService
to have a chance to determine the initial authentication status.
- There are couple places where we need to call
cdr.markForCheck()
. Specifically, those place are invoked via Input Setter.
yarn
yarn serve
- To serve SSR,
yarn dev:ssr