src/app/core/admin/admin-entity-details/admin-entity-field/admin-searchable-checkbox/admin-searchable-checkbox.component.ts
Admin UI component for configuring whether an entity field is searchable. Extends CustomFormControlDirective to integrate with Angular forms.
CustomFormControlDirective<boolean>
| changeDetection | ChangeDetectionStrategy.OnPush |
| providers |
AdminSearchableCheckboxComponent
|
| selector | app-admin-searchable-checkbox |
| standalone | true |
| imports |
MatCheckbox
MatTooltip
|
| styleUrls | ./admin-searchable-checkbox.component.scss |
| templateUrl | ./admin-searchable-checkbox.component.html |
| styleUrl | ./admin-searchable-checkbox.component.scss |
MatCheckbox
MatTooltip
FaIconComponent
ReactiveFormsModule
CustomFormControlDirective<boolean>
OnInit
Properties |
|
Methods |
Inputs |
Outputs |
| dataType | |
Type : string
|
|
| Required : true | |
| entityType | |
Type : EntityConstructor
|
|
| Required : true | |
| fieldId | |
Type : string
|
|
| Required : true | |
| aria-describedby | |
Type : string
|
|
|
Inherited from
CustomFormControlDirective
|
|
| disabled | |
Type : boolean
|
|
|
Inherited from
CustomFormControlDirective
|
|
| ngControl | |
Type : any
|
|
Default value : inject(NgControl, { optional: true, self: true })
|
|
|
Inherited from
CustomFormControlDirective
|
|
| placeholder | |
Type : string
|
|
|
Inherited from
CustomFormControlDirective
|
|
| required | |
Type : boolean
|
|
|
Inherited from
CustomFormControlDirective
|
|
| value | |
Type : T
|
|
|
Inherited from
CustomFormControlDirective
|
|
| valueChange | |
Type : EventEmitter
|
|
|
Inherited from
CustomFormControlDirective
|
|
| writeValue | ||||||||||||
writeValue(value: boolean, shouldEmit: unknown)
|
||||||||||||
|
Inherited from
CustomFormControlDirective
|
||||||||||||
|
Parameters :
Returns :
void
|
| blur |
blur()
|
|
Inherited from
CustomFormControlDirective
|
|
Returns :
void
|
| focus |
focus()
|
|
Inherited from
CustomFormControlDirective
|
|
Returns :
void
|
| onContainerClick | ||||||
onContainerClick(event: MouseEvent)
|
||||||
|
Inherited from
CustomFormControlDirective
|
||||||
|
Parameters :
Returns :
void
|
| registerOnChange | ||||||
registerOnChange(fn: any)
|
||||||
|
Inherited from
CustomFormControlDirective
|
||||||
|
Parameters :
Returns :
void
|
| registerOnTouched | ||||||
registerOnTouched(fn: any)
|
||||||
|
Inherited from
CustomFormControlDirective
|
||||||
|
Parameters :
Returns :
void
|
| setDescribedByIds | ||||||
setDescribedByIds(ids: string[])
|
||||||
|
Inherited from
CustomFormControlDirective
|
||||||
|
Parameters :
Returns :
void
|
| setDisabledState | ||||||
setDisabledState(isDisabled: boolean)
|
||||||
|
Inherited from
CustomFormControlDirective
|
||||||
|
Parameters :
Returns :
void
|
| 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"
|
|
Inherited from
CustomFormControlDirective
|
| elementRef |
Type : unknown
|
Default value : inject<ElementRef<HTMLElement>>(ElementRef)
|
|
Inherited from
CustomFormControlDirective
|
| Readonly enabled |
Type : Signal<boolean>
|
Default value : computed(() => !this._disabled())
|
|
Inherited from
CustomFormControlDirective
|
|
Whether the control is currently enabled, as a signal (tracks disabled). |
| errorStateMatcher |
Type : unknown
|
Default value : inject(ErrorStateMatcher)
|
|
Inherited from
CustomFormControlDirective
|
| id |
Type : unknown
|
Default value : `custom-form-control-${CustomFormControlDirective.nextId++}`
|
|
Inherited from
CustomFormControlDirective
|
| Static nextId |
Type : number
|
Default value : 0
|
|
Inherited from
CustomFormControlDirective
|
| onChange |
Type : unknown
|
Default value : () => {...}
|
|
Inherited from
CustomFormControlDirective
|
| onTouched |
Type : unknown
|
Default value : () => {...}
|
|
Inherited from
CustomFormControlDirective
|
| parentForm |
Type : unknown
|
Default value : inject(NgForm, { optional: true })
|
|
Inherited from
CustomFormControlDirective
|
| parentFormGroup |
Type : unknown
|
Default value : inject(FormGroupDirective, { optional: true })
|
|
Inherited from
CustomFormControlDirective
|
| stateChanges |
Type : unknown
|
Default value : new Subject<void>()
|
|
Inherited from
CustomFormControlDirective
|
| Readonly valueSignal |
Type : Signal<T>
|
Default value : computed(() => this._value())
|
|
Inherited from
CustomFormControlDirective
|
|
The current value of the control as a signal.
Authoritative in both modes: it reflects the bound |
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;
}