Auth directives
Four standalone structural directives read injectAuth() and render or clear
their template as the auth state changes. They are the declarative alternative to a @switch on
auth.status().
The directives
Section titled “The directives”| Class | Selector | Renders when |
|---|---|---|
CvaAuthenticatedDirective |
[cvaAuthenticated] |
auth.isAuthenticated() && !auth.isLoading() |
CvaUnauthenticatedDirective |
[cvaUnauthenticated] |
!auth.isAuthenticated() && !auth.isLoading() |
CvaAuthLoadingDirective |
[cvaAuthLoading] |
auth.isLoading() |
CvaAuthRefreshingDirective |
[cvaAuthRefreshing] |
auth.isRefreshing() |
The first three are mutually exclusive and exhaustive: exactly one of them renders at any moment.
*cvaAuthRefreshing is not exclusive — it overlaps with *cvaAuthenticated, by design.
No inputs, no context
Section titled “No inputs, no context”These directives take no inputs and expose no template context variables. There is nothing to bind and nothing to destructure:
<!-- Correct --><div *cvaAuthenticated>…</div>
<!-- Not supported: there is no input to bind and no context to alias --><div *cvaAuthenticated="something as user">…</div>To read user data, inject your auth service (or injectAuth()) in the component and read it from
the template as usual.
Import them explicitly
Section titled “Import them explicitly”Each directive is standalone and must be added to the imports array of the standalone component
that uses it. Importing only the ones a given template needs keeps the component’s dependency list
honest.
import { CvaAuthenticatedDirective, CvaUnauthenticatedDirective } from 'convex-angular';
@Component({ imports: [CvaAuthenticatedDirective, CvaUnauthenticatedDirective], // …})Refreshing is layered, not swapped
Section titled “Refreshing is layered, not swapped”Remember that 'refreshing' is not routine background rotation — Convex only enters it when the
server rejected a token it had previously accepted. See
the state machine.
Example
Section titled “Example”import { Component } from '@angular/core';import { CvaAuthLoadingDirective, CvaAuthRefreshingDirective, CvaAuthenticatedDirective, CvaUnauthenticatedDirective,} from 'convex-angular';
@Component({ selector: 'app-shell', imports: [ CvaAuthenticatedDirective, CvaUnauthenticatedDirective, CvaAuthLoadingDirective, CvaAuthRefreshingDirective, ], template: ` <p *cvaAuthLoading>Checking your session…</p>
<!-- Stays mounted while the session is refreshing. --> <section *cvaAuthenticated> <h1>Dashboard</h1> </section>
<!-- Layered on top of the still-mounted authenticated content. --> <div *cvaAuthRefreshing role="status" class="banner">Reconnecting your session…</div>
<section *cvaUnauthenticated> <h1>Welcome</h1> <a href="/login">Sign in</a> </section> `,})export class ShellComponent {}Choosing between directives and @switch
Section titled “Choosing between directives and @switch”Directives are terser when each branch is a self-contained block. A @switch on auth.status()
is clearer when you need all four states in one place, or when you want the 'refreshing' branch
to be visibly distinct rather than additive. Both read the same shared state object, so mixing
them in one application is fine.
For blocking navigation instead of hiding content, use the route guards.