src/app/core/admin/admin-entity-details/admin-entity-field/admin-searchable-checkbox/admin-searchable-checkbox.component.ts

Description

Admin UI component for configuring whether an entity field is searchable. Extends CustomFormControlDirective to integrate with Angular forms.

Extends

CustomFormControlDirective<boolean>

Implements

OnInit

Example

Metadata

Relationships

Index

Properties
Methods
Inputs
Outputs

Inputs

dataType
Type : string
Required :  true
entityType
Type : EntityConstructor
Required :  true
fieldId
Type : string
Required :  true
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(value: boolean, shouldEmit: unknown)
Parameters :
Name Type Optional Default value
value boolean No
shouldEmit unknown No false
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 isImplicitlySearchable
Type : unknown
Default value : computed(() => { const fieldId = this.fieldId(); const toStringAttributes = this.entityType()?.toStringAttributes ?? []; return !!fieldId && toStringAttributes.includes(fieldId); })
Readonly isSearchableDataType
Type : unknown
Default value : computed(() => this.searchableDataTypes.has(this.dataType()), )
searchableControl
Type : FormControl<boolean>
Readonly showImplicitSearchableNote
Type : unknown
Default value : computed( () => this.isImplicitlySearchable() && !this.isChecked(), )
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 {
  Component,
  computed,
  input,
  OnInit,
  signal,
  ChangeDetectionStrategy,
} from "@angular/core";
import { MatCheckbox } from "@angular/material/checkbox";
import { MatTooltip } from "@angular/material/tooltip";
import { FaIconComponent } from "@fortawesome/angular-fontawesome";
import { CustomFormControlDirective } from "../../../../common-components/basic-autocomplete/custom-form-control.directive";
import { MatFormFieldControl } from "@angular/material/form-field";
import { EntityConstructor } from "../../../../entity/model/entity";
import { FormControl, ReactiveFormsModule } from "@angular/forms";

/**
 * Admin UI component for configuring whether an entity field is searchable.
 * Extends CustomFormControlDirective to integrate with Angular forms.
 */
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-admin-searchable-checkbox",
  imports: [MatCheckbox, MatTooltip, FaIconComponent, ReactiveFormsModule],
  templateUrl: "./admin-searchable-checkbox.component.html",
  styleUrl: "./admin-searchable-checkbox.component.scss",
  providers: [
    {
      provide: MatFormFieldControl,
      useExisting: AdminSearchableCheckboxComponent,
    },
  ],
})
export class AdminSearchableCheckboxComponent
  extends CustomFormControlDirective<boolean>
  implements OnInit
{
  entityType = input.required<EntityConstructor>();
  fieldId = input.required<string>();
  dataType = input.required<string>();

  searchableControl: FormControl<boolean>;
  private readonly isChecked = signal(false);

  private readonly searchableDataTypes = new Set([
    "string",
    "long-text",
    "email",
    "url",
    "number",
  ]);

  readonly isSearchableDataType = computed(() =>
    this.searchableDataTypes.has(this.dataType()),
  );

  readonly isImplicitlySearchable = computed(() => {
    const fieldId = this.fieldId();
    const toStringAttributes = this.entityType()?.toStringAttributes ?? [];
    return !!fieldId && toStringAttributes.includes(fieldId);
  });

  readonly showImplicitSearchableNote = computed(
    () => this.isImplicitlySearchable() && !this.isChecked(),
  );

  ngOnInit() {
    this.searchableControl = new FormControl(this.value ?? false);
    this.isChecked.set(this.value ?? false);

    this.searchableControl.valueChanges.subscribe((value) => {
      this.isChecked.set(!!value);
      if (this.value !== value) {
        this.value = value;
      }
    });

    this.applySearchableAvailability();
  }

  override writeValue(value: boolean, shouldEmit = false): void {
    const prevValue = this.value;
    super.writeValue(value, shouldEmit);
    this.isChecked.set(!!value);
    if (this.searchableControl && prevValue !== value) {
      this.searchableControl.setValue(value ?? false, { emitEvent: false });
      this.applySearchableAvailability();
    }
  }

  private applySearchableAvailability() {
    if (!this.searchableControl) {
      return;
    }

    if (!this.isSearchableDataType()) {
      this.searchableControl.setValue(false);
      this.searchableControl.disable({ emitEvent: false });
      return;
    }

    if (this.searchableControl.disabled) {
      this.searchableControl.enable({ emitEvent: false });
    }
  }
}
<div
  class="margin-top-regular"
  matTooltip="Search for this type of field is not supported."
  matTooltipPosition="before"
  [matTooltipDisabled]="isSearchableDataType()"
  i18n-matTooltip
>
  <mat-checkbox [formControl]="searchableControl">
    <span i18n>Searchable</span>
    <fa-icon
      icon="question-circle"
      matTooltip="By enabling the checkbox, you can find the record from the global search by inputting the value."
      i18n-matTooltip
    ></fa-icon>
  </mat-checkbox>
  @if (showImplicitSearchableNote()) {
    <div class="hint-text" i18n>
      This field is already searchable because it is part of the record's
      display name.
    </div>
  }
</div>

./admin-searchable-checkbox.component.scss

:host {
  display: block;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""