src/app/features/todos/recurring-interval/edit-recurring-interval/edit-recurring-interval.component.ts
Form field to edit a time interval for repetitions.
The schema or config accepts pre-defined options for the dropdown as additional.
CustomFormControlDirective<any>
| changeDetection | ChangeDetectionStrategy.OnPush |
| providers |
EditRecurringIntervalComponent
|
| selector | app-edit-recurring-interval |
| standalone | true |
| imports |
MatInputModule
FontAwesomeModule
MatSelectModule
|
| styleUrls | ./edit-recurring-interval.component.scss |
| templateUrl | ./edit-recurring-interval.component.html |
No results matching.
MatInputModule
ReactiveFormsModule
FontAwesomeModule
MatSelectModule
CustomFormControlDirective<any>
OnInit
EditComponent
Properties |
Methods |
Inputs |
Outputs |
| formFieldConfig | |
Type : FormFieldConfig
|
|
| 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
|
|
| openCustomIntervalSelection | ||||||
openCustomIntervalSelection(event: MatOptionSelectionChange<TimeInterval>)
|
||||||
|
Parameters :
Returns :
void
|
| resetSelection |
resetSelection()
|
|
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
|
| writeValue | |||||||||||||||
writeValue(value: T, notifyFormControl: unknown)
|
|||||||||||||||
|
Inherited from
CustomFormControlDirective
|
|||||||||||||||
|
Implementation for Angular ControlValueAccessor interface that links the form control value to the component value
Parameters :
Returns :
void
|
| compareOptionFun |
Type : unknown
|
Default value : () => {...}
|
| 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 { FormFieldConfig } from "#src/app/core/common-components/entity-form/FormConfig";
import {
ChangeDetectionStrategy,
Component,
inject,
input,
linkedSignal,
OnInit,
} from "@angular/core";
import { ReactiveFormsModule } from "@angular/forms";
import { MatOptionSelectionChange } from "@angular/material/core";
import { MatDialog } from "@angular/material/dialog";
import { MatFormFieldControl } from "@angular/material/form-field";
import { MatInputModule } from "@angular/material/input";
import { MatSelectModule } from "@angular/material/select";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { CustomFormControlDirective } from "../../../../core/common-components/basic-autocomplete/custom-form-control.directive";
import { DynamicComponent } from "../../../../core/config/dynamic-components/dynamic-component.decorator";
import { EditComponent } from "../../../../core/entity/entity-field-edit/dynamic-edit/edit-component.interface";
import { CustomIntervalComponent } from "../custom-interval/custom-interval.component";
import { generateLabelFromInterval, TimeInterval } from "../time-interval";
/**
* Form field to edit a time interval for repetitions.
*
* The schema or config accepts pre-defined options for the dropdown as `additional`.
*/
@DynamicComponent("EditRecurringInterval")
@Component({
selector: "app-edit-recurring-interval",
templateUrl: "./edit-recurring-interval.component.html",
styleUrls: ["./edit-recurring-interval.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
MatInputModule,
ReactiveFormsModule,
FontAwesomeModule,
MatSelectModule,
],
providers: [
{
provide: MatFormFieldControl,
useExisting: EditRecurringIntervalComponent,
},
],
})
export class EditRecurringIntervalComponent
extends CustomFormControlDirective<any>
implements OnInit, EditComponent
{
private matDialog = inject(MatDialog);
formFieldConfig = input<FormFieldConfig>();
predefinedIntervals = linkedSignal<
{ label: string; interval: TimeInterval }[]
>(
() =>
this.formFieldConfig()?.additional ?? [
{
label: $localize`:default interval select option:weekly`,
interval: { amount: 1, unit: "week" },
},
{
label: $localize`:default interval select option:monthly`,
interval: { amount: 1, unit: "month" },
},
],
);
compareOptionFun = (a: TimeInterval, b: TimeInterval) =>
JSON.stringify(a) === JSON.stringify(b);
ngOnInit(): void {
// re-create active custom interval if necessary
this.addCustomInterval(this.formControl.value);
}
resetSelection() {
this.formControl.setValue(undefined);
}
openCustomIntervalSelection(event: MatOptionSelectionChange<TimeInterval>) {
if (!event.isUserInput) {
return;
}
const previousSelectedInterval = this.formControl.value;
this.matDialog
.open(CustomIntervalComponent)
.afterClosed()
.subscribe((result: TimeInterval) => {
if (result === undefined) {
// keep unchanged, i.e. revert to previous selection
this.formControl.setValue(previousSelectedInterval);
} else {
this.addCustomInterval(result);
this.formControl.setValue(result);
this.formControl.markAsDirty();
}
});
}
private addCustomInterval(interval: TimeInterval) {
if (!interval) {
return;
}
const selectedOptionValue = this.predefinedIntervals().find((o) =>
this.compareOptionFun(interval, o.interval),
)?.interval;
if (!selectedOptionValue) {
this.predefinedIntervals.update((prev) => [
...prev,
{ label: generateLabelFromInterval(interval), interval },
]);
}
}
}
<mat-select [formControl]="formControl" [compareWith]="compareOptionFun">
@for (o of predefinedIntervals(); track o.label) {
<mat-option [value]="o.interval">
{{ o.label }}
</mat-option>
}
<mat-option
(onSelectionChange)="openCustomIntervalSelection($event)"
class="special-option"
>
<fa-icon icon="tools" [fixedWidth]="true"></fa-icon>
<span i18n="recurring interval option">define other interval</span>
</mat-option>
<mat-option
[value]="undefined"
(onSelectionChange)="resetSelection()"
class="special-option"
>
<fa-icon icon="xmark" [fixedWidth]="true"></fa-icon>
<span i18n="recurring interval option">does not repeat</span>
</mat-option>
</mat-select>
./edit-recurring-interval.component.scss
.special-option {
font-style: italic;
}
.suffix-action {
display: inline;
}
.tooltip-suffix {
margin: 4px;
}