Details

The <smart-details> component renders a list of model fields decorated with @Field({ details: true }). It is a wrapper that delegates to DetailsStandardComponent by default and can be replaced via DETAILS_STANDARD_COMPONENT_TOKEN.


Usage

<smart-details [options]="options" />

Components

DetailsComponent (<smart-details>)

Main wrapper. Renders DetailsStandardComponent by default. When DETAILS_STANDARD_COMPONENT_TOKEN is provided, renders the injected component via NgComponentOutlet, passing options and class as inputs.

DetailsStandardComponent (<smart-details-standard>)

Default concrete implementation. Generic Tailwind-styled <dl> placeholder that iterates over fields and renders each via <smart-detail>.

DetailsBaseComponent (abstract)

Abstract base directive. Computes fields from model decorators (with permission and specification filters), exposes the typed item signal, and tracks cellPipe/componentFactories. Extend it to build custom details implementations.

API

Inputs

InputTypeDefaultDescription
optionsInputSignal<IDetailsOptions<T>>undefinedDetails configuration
classInputSignal<string> (alias cssClass)''External CSS classes on the container

DETAILS_STANDARD_COMPONENT_TOKEN

InjectionToken that allows replacing the default DetailsStandardComponent with a custom implementation. Provide a Type<DetailsBaseComponent<T>>.

Extending the base class

import { ChangeDetectionStrategy, Component, signal } from '@angular/core';

import {
  DetailsBaseComponent,
  DetailsComponent,
  DETAILS_STANDARD_COMPONENT_TOKEN,
  IDetailsOptions,
} from '@smartsoft001/angular';
import { Field, Model } from '@smartsoft001/models';

@Model({})
class ApplicantModel {
  id = 'applicant-1';

  @Field({ details: true })
  name = 'Margot Foster';

  @Field({ details: true })
  position = 'Backend Developer';
}

/**
 * A custom details layout built on `DetailsBaseComponent`.
 *
 * The base reads the `@Field({ details: ... })` metadata off the model class
 * given in `options.type` and exposes the result as `fields`, alongside the
 * `item` and `loading` signals taken from the options. A custom implementation
 * decides only how a row looks — here a flat definition list instead of the
 * grid of the standard variation.
 */
@Component({
  selector: 'docs-custom-details',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <dl class="docs-details">
      @for (field of fields; track field.key) {
        <div class="docs-details__row">
          <dt>{{ field.key }}</dt>
          <dd>{{ display(field.key) }}</dd>
        </div>
      }
    </dl>
  `,
})
export class CustomDetailsComponent extends DetailsBaseComponent<ApplicantModel> {
  // `item` is a signal of the model instance, so values are read by field key.
  display(key: string): string {
    const item = this.item?.() as Record<string, unknown> | undefined;
    return String(item?.[key] ?? '');
  }
}

/**
 * Registering the implementation against `DETAILS_STANDARD_COMPONENT_TOKEN`
 * makes every `<smart-details>` in this injector render it instead of the
 * standard variation.
 */
@Component({
  selector: 'docs-details-custom-example',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [DetailsComponent],
  providers: [
    {
      provide: DETAILS_STANDARD_COMPONENT_TOKEN,
      useValue: CustomDetailsComponent,
    },
  ],
  template: `<smart-details [options]="options" />`,
})
export class DetailsCustomExampleComponent {
  options: IDetailsOptions<ApplicantModel> = {
    type: ApplicantModel,
    item: signal(new ApplicantModel()),
  };
}

Field Rendering

Each field is rendered via <smart-detail>. The actual rendering of a single field by FieldType (text, email, address, image, attachment, …) is dispatched inside <smart-detail> itself. See the angular-components-detail skill for per-field details.

Source

The component lives in packages/shared/angular/src/lib/components/details and is documented for Claude Code by the angular-components-details skill.