Skip to content

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().

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.

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.

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],
// …
})

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.

shell.component.ts
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 {}

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.