src/app/features/public-form/edit-publicform-route/edit-publicform-route.component.ts

Description

Special Form Field to edit an ID and copy the full public-form URL generated based on this.

Extends

CustomFormControlDirective<string>

Implements

OnInit EditComponent

Example

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

copyToClipboard
copyToClipboard()
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
writeValue
writeValue(value: T, notifyFormControl: unknown)

Implementation for Angular ControlValueAccessor interface that links the form control value to the component value

Parameters :
Name Type Optional Default value Description
value T No

The new value to set

notifyFormControl unknown No false

Whether to notify the FormControl of this change (for internal updates)

Returns : void

Properties

prefixValue
Type : string
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 {
  ChangeDetectionStrategy,
  Component,
  inject,
  input,
  OnInit,
} from "@angular/core";
import {
  AbstractControl,
  ReactiveFormsModule,
  ValidatorFn,
  Validators,
} from "@angular/forms";
import { MatIconButton } from "@angular/material/button";
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 { AlertService } from "../../../core/alerts/alert.service";
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 { Entity } from "../../../core/entity/model/entity";
import { PublicFormConfig } from "../public-form-config";

const noSpecialUrlChars: ValidatorFn = (control: AbstractControl) => {
  const value: string = control.value;
  if (value && !/^[a-zA-Z\d\-_]+$/.test(value)) {
    return {
      pattern: {
        errorMessage: $localize`The link ID may only contain lowercase letters, digits, hyphens and underscores`,
      },
    };
  }
  return null;
};

/**
 * Special Form Field to edit an ID and copy the full public-form URL generated based on this.
 */
@DynamicComponent("EditPublicformRoute")
@Component({
  selector: "app-edit-publicform-route",
  standalone: true,
  imports: [
    ReactiveFormsModule,
    MatInputModule,
    FontAwesomeModule,
    MatIconButton,
    MatTooltipModule,
  ],
  templateUrl: "./edit-publicform-route.component.html",
  styleUrls: ["./edit-publicform-route.component.scss"],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    { provide: MatFormFieldControl, useExisting: EditPublicformRouteComponent },
  ],
})
export class EditPublicformRouteComponent
  extends CustomFormControlDirective<string>
  implements OnInit, EditComponent
{
  private alertService = inject(AlertService);

  formFieldConfig = input<FormFieldConfig>();
  entity = input<Entity>();

  prefixValue: string;
  private fullPrefixUrl: string;

  ngOnInit(): void {
    const publicFormConfig: PublicFormConfig = {
      route: this.formControl.getRawValue(),
    } as Partial<PublicFormConfig> as PublicFormConfig;

    this.formControl.setValidators([Validators.required, noSpecialUrlChars]);
    this.formControl.setValue(publicFormConfig.route);

    this.fullPrefixUrl = `${window.location.origin}/public-form/form/`;
    this.prefixValue = `${window.location.origin}/.../`;
  }

  copyToClipboard(): void {
    const fullUrl = this.fullPrefixUrl + (this.formControl.value || "");
    navigator.clipboard.writeText(fullUrl).then(() => {
      this.alertService.addInfo("Link copied: " + fullUrl);
    });
  }
}
<div class="form-link-container">
  <div
    class="readonly-prefix"
    matTooltip="The identifier that is part of the link (URL) through which users can access this form"
    i18n-matTooltip
  >
    {{ prefixValue }}
  </div>
  <div class="input-button-row">
    <input
      matInput
      [formControl]="formControl"
      placeholder="Enter Form Link ID"
      i18n-placeholder
      class="editable-input"
    />
    <button
      mat-icon-button
      matTooltip="Copy the link to share or paste it somewhere else"
      i18n-matTooltip
      (click)="copyToClipboard()"
      class="copy-button"
    >
      <fa-icon [icon]="['far', 'copy']"></fa-icon>
    </button>
  </div>
</div>

./edit-publicform-route.component.scss

@use "variables/breakpoints";
@use "variables/colors";

.form-link-container {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.readonly-prefix {
  overflow-wrap: break-word;
  opacity: 0.4;
  font-size: 0.875rem;
}

.input-button-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
}

.editable-input {
  flex: 1;
  min-width: 0;
}

:host ::ng-deep .mat-mdc-form-field-infix {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.copy-button {
  pointer-events: auto !important;
  flex-shrink: 0;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""