src/app/features/location/edit-location/edit-location.component.ts
Input to select and view an address on a map.
CustomFormControlDirective<GeoLocation>
| changeDetection | ChangeDetectionStrategy.OnPush |
| providers |
EditLocationComponent
|
| selector | app-edit-location |
| standalone | true |
| imports |
MatInput
MatIconButton
MatTooltip
MatTooltipModule
|
| styleUrls | ./edit-location.component.scss, |
| templateUrl | ./edit-location.component.html |
No results matching.
FormsModule
MatInput
MatIconButton
FaIconComponent
MatTooltip
ReactiveFormsModule
MatTooltipModule
CustomFormControlDirective<GeoLocation>
EditComponent
Properties |
|
Methods |
Inputs |
Outputs |
| autoLookup | |
Type : boolean
|
|
Default value : true
|
|
|
Automatically run an address lookup when the user leaves the input field. |
|
| 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
|
|
| onContainerClick |
onContainerClick()
|
|
Inherited from
CustomFormControlDirective
|
|
Returns :
void
|
| openMap |
openMap()
|
|
Returns :
void
|
| blur |
blur()
|
|
Inherited from
CustomFormControlDirective
|
|
Returns :
void
|
| focus |
focus()
|
|
Inherited from
CustomFormControlDirective
|
|
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
|
| 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 {
ChangeDetectionStrategy,
Component,
inject,
input,
} from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { MatIconButton } from "@angular/material/button";
import { MatDialog } from "@angular/material/dialog";
import { MatFormFieldControl } from "@angular/material/form-field";
import { MatInput } from "@angular/material/input";
import { MatTooltip, MatTooltipModule } from "@angular/material/tooltip";
import { FaIconComponent } from "@fortawesome/angular-fontawesome";
import { filter, map } from "rxjs/operators";
import { CustomFormControlDirective } from "../../../core/common-components/basic-autocomplete/custom-form-control.directive";
import { FormFieldConfig } from "../../../core/common-components/entity-form/FormConfig";
import { DynamicComponent } from "../../../core/config/dynamic-components/dynamic-component.decorator";
import { EditComponent } from "../../../core/entity/entity-field-edit/dynamic-edit/edit-component.interface";
import { GeoLocation } from "../geo-location";
import {
MapPopupComponent,
MapPopupConfig,
} from "../map-popup/map-popup.component";
/**
* Input to select and view an address on a map.
*/
@DynamicComponent("EditLocation")
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-edit-location",
templateUrl: "./edit-location.component.html",
styleUrls: [
"./edit-location.component.scss",
"../../../core/entity/entity-field-edit/dynamic-edit/dynamic-edit.component.scss",
],
imports: [
FormsModule,
MatInput,
MatIconButton,
FaIconComponent,
MatTooltip,
ReactiveFormsModule,
MatTooltipModule,
],
providers: [
{ provide: MatFormFieldControl, useExisting: EditLocationComponent },
],
})
export class EditLocationComponent
extends CustomFormControlDirective<GeoLocation>
implements EditComponent
{
private readonly dialog = inject(MatDialog);
formFieldConfig = input<FormFieldConfig>();
/**
* Automatically run an address lookup when the user leaves the input field.
*/
autoLookup = input<boolean>(true);
override onContainerClick() {
if (!this.disabled) {
this.openMap();
}
}
openMap() {
const config: MapPopupConfig = {
selectedLocation: this.valueSignal(),
disabled: this.disabled,
};
const ref = this.dialog.open(MapPopupComponent, {
width: "90%",
height: "90vh",
autoFocus: ".address-search-input",
restoreFocus: false,
data: config,
});
if (!this.disabled) {
ref
.afterClosed()
.pipe(
filter((result: GeoLocation[] | undefined) => {
return Array.isArray(result);
}),
map((result: GeoLocation[]) => result[0]),
filter(
(result: GeoLocation | undefined) =>
JSON.stringify(result) !== JSON.stringify(this.valueSignal()),
), // nothing changed, skip
)
.subscribe((result: GeoLocation) => {
if (this.ngControl?.control) {
this.ngControl.control.setValue(result);
} else {
this.value = result;
}
});
}
}
}
<div
class="flex-row gap-regular align-end"
[class.clickable]="enabled()"
(click)="onContainerClick(); $event.stopPropagation()"
>
<textarea
#inputElement
matInput
[title]="placeholder"
[disabled]="!enabled()"
readonly
[value]="
valueSignal()?.locationString ??
valueSignal()?.geoLookup?.display_name ??
''
"
rows="3"
></textarea>
@if (valueSignal()?.geoLookup) {
<button
(click)="openMap(); $event.stopPropagation()"
mat-icon-button
type="button"
class="input-action-button"
matTooltip="Show the location marked on the map."
i18n-matTooltip
>
<fa-icon icon="map-location-dot"></fa-icon>
</button>
} @else {
<div
matTooltip="No location marked yet. Edit and search a location on the map here."
i18n-matTooltip
>
<button
(click)="openMap(); $event.stopPropagation()"
mat-icon-button
type="button"
class="input-action-button"
[disabled]="!enabled()"
>
<fa-icon icon="magnifying-glass-location"></fa-icon>
</button>
</div>
}
</div>
./edit-location.component.scss
:host {
pointer-events: auto;
}
.clickable,
.clickable * {
cursor: pointer;
}
../../../core/entity/entity-field-edit/dynamic-edit/dynamic-edit.component.scss
.input-action-button {
margin: -12px;
}