import { Component } from '@angular/core'; import type { Resource } from '@angular/core'; import { HeadingComponent } from '@shared/ui/heading/heading.component'; import { ASYNC } from '@shared/ui/async/async.component'; import { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component'; import { ConceptCardComponent } from './concept-card.component'; import { SNIPPETS } from './snippets.generated'; import { highlightTs } from './highlight-ts'; /** Minimal fake Resource so can be driven through every state without HTTP. */ function fakeResource(status: string, value?: T, error?: Error): Resource { return { value: () => value as T, status: () => status, error: () => error, hasValue: () => value !== undefined, reload: () => {}, } as unknown as Resource; } /** Section 2: RemoteData fold. One value with four mutually exclusive states, instead of three loose booleans. Composition-only; owns its own fake resources. Each of the four demo states nests its own `` for its label — a plain `.tag` element written here would carry this section's scope, not the card's, and stay unstyled. */ @Component({ selector: 'app-concepts-remote-data-section', imports: [HeadingComponent, ...ASYNC, SkeletonComponent, ConceptCardComponent], template: `
2 · RemoteData fold

Eén waarde met vier elkaar uitsluitende toestanden in plaats van drie losse booleans.

{{ v }} {{ v }} {{ v }}
    @for (i of successRes.value(); track i) {
  • {{ i }}
  • }

Een nieuwe variant toevoegen breekt de compile via assertNever tot je hem afhandelt.

`, }) export class RemoteDataSection { isEmpty = (v: string[]) => !v || v.length === 0; loadingRes = fakeResource('loading'); emptyRes = fakeResource('resolved', []); errorRes = fakeResource('error', undefined, new Error('Demo')); successRes = fakeResource('resolved', ['Huisartsgeneeskunde', 'Spoedeisende hulp']); protected readonly code: Record = { fold: highlightTs(SNIPPETS['fold']) }; protected readonly src: Record = { fold: 'shared/application/remote-data.ts' }; }