src/app/core/basic-datatypes/date-with-age/edit-age/edit-age.component.ts

Extends

CustomFormControlDirective<DateWithAge>

Implements

EditComponent OnInit

Metadata

Relationships

Used by

No results matching.

Depends on

Index

Properties
Methods
Inputs
Outputs

Inputs

entity
Type : Entity
formFieldConfig
Type : FormFieldConfig
aria-describedby
Type : string
disabled
Type : boolean
ngControl
Type : any
Default value : inject(NgControl, { optional: true, self: true })
placeholder
Type : string
required
Type : boolean
value
Type : T

Outputs

valueChange
Type : EventEmitter

Methods

writeValue
writeValue(newValue: DateWithAge | Date)
Parameters :
Name Type Optional
newValue DateWithAge | Date No
Returns : void
blur
blur()
Returns : void
focus
focus()
Returns : void
onContainerClick
onContainerClick(event: MouseEvent)
Parameters :
Name Type Optional
event MouseEvent No
Returns : void
registerOnChange
registerOnChange(fn: any)
Parameters :
Name Type Optional
fn any No
Returns : void
registerOnTouched
registerOnTouched(fn: any)
Parameters :
Name Type Optional
fn any No
Returns : void
setDescribedByIds
setDescribedByIds(ids: string[])
Parameters :
Name Type Optional
ids string[] No
Returns : void
setDisabledState
setDisabledState(isDisabled: boolean)
Parameters :
Name Type Optional
isDisabled boolean No
Returns : void

Properties

Readonly age
Type : unknown
Default value : computed(() => this.valueSignal()?.age ?? null)

The age derived from the current date value, kept reactive via the base valueSignal.

controlType
Type : string
Default value : "custom-control"
elementRef
Type : unknown
Default value : inject<ElementRef<HTMLElement>>(ElementRef)
Readonly enabled
Type : Signal<boolean>
Default value : computed(() => !this._disabled())

Whether the control is currently enabled, as a signal (tracks disabled).

errorStateMatcher
Type : unknown
Default value : inject(ErrorStateMatcher)
id
Type : unknown
Default value : `custom-form-control-${CustomFormControlDirective.nextId++}`
Static nextId
Type : number
Default value : 0
onChange
Type : unknown
Default value : () => {...}
onTouched
Type : unknown
Default value : () => {...}
parentForm
Type : unknown
Default value : inject(NgForm, { optional: true })
parentFormGroup
Type : unknown
Default value : inject(FormGroupDirective, { optional: true })
stateChanges
Type : unknown
Default value : new Subject<void>()
Readonly valueSignal
Type : Signal<T>
Default value : computed(() => this._value())

The current value of the control as a signal. Authoritative in both modes: it reflects the bound FormControl (synced in ngDoCheck) as well as [(value)] / writeValue updates.

import { Entity } from "#src/app/core/entity/model/entity";
import {
  Component,
  computed,
  input,
  OnInit,
  ChangeDetectionStrategy,
} from "@angular/core";
import { ReactiveFormsModule } from "@angular/forms";
import { MatDatepickerModule } from "@angular/material/datepicker";
import { MatFormFieldControl } from "@angular/material/form-field";
import { MatInputModule } from "@angular/material/input";
import { MatTooltipModule } from "@angular/material/tooltip";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { CustomFormControlDirective } from "../../../common-components/basic-autocomplete/custom-form-control.directive";
import { FormFieldConfig } from "../../../common-components/entity-form/FormConfig";
import { DynamicComponent } from "../../../config/dynamic-components/dynamic-component.decorator";
import { EditComponent } from "../../../entity/entity-field-edit/dynamic-edit/edit-component.interface";
import { DateWithAge } from "../dateWithAge";

@DynamicComponent("EditAge")
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-edit-age",
  templateUrl: "./edit-age.component.html",
  styleUrls: [
    "../../../entity/entity-field-edit/dynamic-edit/dynamic-edit.component.scss",
    "./edit-age.component.scss",
  ],
  imports: [
    ReactiveFormsModule,
    MatInputModule,
    MatDatepickerModule,
    FontAwesomeModule,
    MatTooltipModule,
  ],
  providers: [{ provide: MatFormFieldControl, useExisting: EditAgeComponent }],
})
export class EditAgeComponent
  extends CustomFormControlDirective<DateWithAge>
  implements EditComponent, OnInit
{
  formFieldConfig = input<FormFieldConfig>();
  entity = input<Entity>();

  /** The age derived from the current date value, kept reactive via the base `valueSignal`. */
  readonly age = computed(() => this.valueSignal()?.age ?? null);

  override writeValue(newValue: DateWithAge | Date) {
    if (newValue instanceof Date && !(newValue instanceof DateWithAge)) {
      super.writeValue(new DateWithAge(newValue));
    } else {
      super.writeValue(newValue);
    }
  }

  ngOnInit() {
    // Ensure the stored value is always a DateWithAge (so `.age` is available).
    // In EditComponent mode the value flows through the control, not writeValue.
    this.formControl.valueChanges.subscribe((newValue) => {
      if (newValue instanceof Date && !(newValue instanceof DateWithAge)) {
        this.formControl.setValue(new DateWithAge(newValue));
      }
    });
  }
}
<div class="flex-row align-center gap-small">
  @if (
    !(
      entity()?.anonymized &&
      formFieldConfig()?.anonymize === "retain-anonymized"
    )
  ) {
    <input
      matInput
      [formControl]="formControl"
      [matDatepicker]="dateOfBirthDatepicker"
      class="flex-grow"
    />

    <mat-datepicker-toggle
      [for]="dateOfBirthDatepicker"
      class="input-action-button"
    ></mat-datepicker-toggle>
    <mat-datepicker #dateOfBirthDatepicker></mat-datepicker>
  }

  <div class="flex-row align-center gap-small age-display-container">
    <span class="age-label" i18n="Label for the age display">Age:</span>
    <span>{{ age() || "-" }}</span>

    <fa-icon
      icon="question-circle"
      i18n-matTooltip="Tooltip for the disabled age field"
      matTooltip="This field is read-only. Edit the date field to update the age. You can select Jan 1st if you don't know the exact date."
      class="age-help-icon"
      [class.visible]="enabled()"
      [class.hidden]="!enabled()"
    ></fa-icon>
  </div>
</div>

../../../entity/entity-field-edit/dynamic-edit/dynamic-edit.component.scss

.input-action-button {
  margin: -12px;
}

./edit-age.component.scss

@use "variables/colors";

.age-display-container {
  margin-left: 8px;
  margin-top: -8px;
  padding: 4px 8px;
  background-color: rgba(0, 0, 0, 0.04);
  border-radius: 4px;
  border: 1px solid rgba(0, 0, 0, 0.12);
}

input[matInput] {
  min-width: 6.5rem;
}

.age-label {
  font-size: 12px;
  color: rgba(0, 0, 0, 0.6);
  font-weight: 500;
}

.age-help-icon {
  color: rgba(0, 0, 0, 0.6);
  cursor: help;

  &.hidden {
    display: none;
  }

  &.visible {
    visibility: visible;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""