src/app/core/common-components/entity-fields-menu/entity-fields-menu.component.ts

Implements

OnInit

Metadata

Relationships

Index

Properties
Inputs
Outputs

Constructor

constructor()

Inputs

activeFields
Type : ColumnConfig[]
Default value : []
availableFields
Type : ColumnConfig[]
Default value : []
entityType
Type : EntityConstructor

Outputs

activeFieldsChange
Type : ColumnConfig[]

Properties

Readonly _availableFields
Type : unknown
Default value : computed<FormFieldConfig[]>(() => { const entityType = this.entityType(); const fieldsConfig: FormFieldConfig[] = this.availableFields() .map((field) => { const mappedField = this.entityFormService && entityType ? this.entityFormService.extendFormFieldConfig(field, entityType) : toFormFieldConfig(field); if (typeof field === "object") { mappedField["_customField"] = true; } return mappedField; }) .filter( (field) => field["_customField"] || (!field.isInternalField && field.label), ); const deduplicatedFieldsById: Record<string, FormFieldConfig> = {}; for (const field of fieldsConfig) { if (!deduplicatedFieldsById[field.id]) { deduplicatedFieldsById[field.id] = field; } } return Object.values(deduplicatedFieldsById); })
selectedFieldsControl
Type : unknown
Default value : new FormControl<string[]>([])
import {
  ChangeDetectionStrategy,
  Component,
  computed,
  DestroyRef,
  effect,
  inject,
  input,
  OnInit,
  output,
} from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { EntityConstructor } from "../../entity/model/entity";
import {
  ColumnConfig,
  FormFieldConfig,
  toFormFieldConfig,
} from "../entity-form/FormConfig";
import { EntityFormService } from "../entity-form/entity-form.service";
import { FormControl, ReactiveFormsModule } from "@angular/forms";
import { MatFormFieldModule } from "@angular/material/form-field";
import { EntityFieldSelectComponent } from "app/core/entity/entity-field-select/entity-field-select.component";

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-entity-fields-menu",
  imports: [
    MatFormFieldModule,
    ReactiveFormsModule,
    EntityFieldSelectComponent,
  ],
  templateUrl: "./entity-fields-menu.component.html",
  styleUrl: "./entity-fields-menu.component.scss",
})
export class EntityFieldsMenuComponent implements OnInit {
  private entityFormService = inject(EntityFormService, { optional: true });
  private readonly destroyRef = inject(DestroyRef);

  entityType = input<EntityConstructor>();
  availableFields = input<ColumnConfig[]>([]);
  activeFields = input<ColumnConfig[]>([]);
  activeFieldsChange = output<ColumnConfig[]>();
  selectedFieldsControl = new FormControl<string[]>([]);

  readonly _availableFields = computed<FormFieldConfig[]>(() => {
    const entityType = this.entityType();
    const fieldsConfig: FormFieldConfig[] = this.availableFields()
      .map((field) => {
        const mappedField =
          this.entityFormService && entityType
            ? this.entityFormService.extendFormFieldConfig(field, entityType)
            : toFormFieldConfig(field);

        if (typeof field === "object") {
          mappedField["_customField"] = true;
        }

        return mappedField;
      })
      .filter(
        (field) =>
          field["_customField"] || (!field.isInternalField && field.label),
      );

    const deduplicatedFieldsById: Record<string, FormFieldConfig> = {};
    for (const field of fieldsConfig) {
      if (!deduplicatedFieldsById[field.id]) {
        deduplicatedFieldsById[field.id] = field;
      }
    }
    return Object.values(deduplicatedFieldsById);
  });

  constructor() {
    effect(() => {
      const selectedFields = (this.activeFields() ?? []).map((field) =>
        typeof field === "string" ? field : field.id,
      );
      const currentSelection = this.selectedFieldsControl.value ?? [];

      if (
        currentSelection.length === selectedFields.length &&
        currentSelection.every(
          (value, index) => value === selectedFields[index],
        )
      ) {
        return;
      }

      this.selectedFieldsControl.setValue(selectedFields, { emitEvent: false });
    });
  }

  ngOnInit() {
    this.selectedFieldsControl.valueChanges
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe((value: string[]) => {
        const mappedFields: ColumnConfig[] = value.map((v) => {
          const availableField = this._availableFields().find(
            (f) => f.id === v,
          );

          if (availableField?.["_customField"]) {
            const result = { ...availableField };
            delete result["_customField"];
            return result;
          } else return v;
        });

        this.activeFieldsChange.emit(mappedFields);
      });
  }
}
<mat-form-field>
  <app-entity-field-select
    [entityType]="entityType()"
    [formControl]="selectedFieldsControl"
    [options]="_availableFields()"
    [multi]="true"
  />
</mat-form-field>

./entity-fields-menu.component.scss

@use "variables/breakpoints";

.square-button {
  border-radius: 0 0 0 4px;
}
:host ::ng-deep .mat-mdc-icon-button .mat-mdc-button-persistent-ripple {
  border-radius: 0 0 0 4px;
}

@media screen and (min-width: breakpoints.$md) {
  :host ::ng-deep .mat-mdc-form-field {
    width: 30%;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""