File

src/app/shared/widgets/select-combo/select-combo.component.ts

Index

Properties

Properties

allowEmpty
allowEmpty: boolean
Type : boolean

Allow a empty value as option (@default:true)

clearable
clearable: boolean
Type : boolean

true to show the clear button (@default:true)

customClass
customClass: string
Type : string

Sets the custom css class

disabled
disabled: boolean
Type : boolean

true to disable the component (@default:false)

displayKey
displayKey: string
Type : string

Value(relates to select options) displayed description key (@default:description)

groupKey
groupKey: string
Type : string

If the data contains groups, this field either contains the parent reference or the child options

groupStrategy
groupStrategy: GroupByStrategy
Type : GroupByStrategy

"nested", groupKey should contain an array of options, "parent-reference": child options reference the valueKey field of their parent

identifier
identifier: string
Type : string

Identifier and name of this field

multiple
multiple: boolean
Type : boolean

Allow multiple selection (@default: false)

openOnFocus
openOnFocus: boolean
Type : boolean

Open options on focus (example over tabulator) (@default:false)

optionsDataKey
optionsDataKey: string
Type : string

The key of embedded options-data in response of optionsDataUrl

optionsDataUrl
optionsDataUrl: string
Type : string

Fetch options of the select element from a url.

placeholder
placeholder: string
Type : string

Placeholder string to display

preselectedValues
preselectedValues: string[]
Type : string[]

Id string-array of preselected values(relates to select options) (identifiers)

showAllPlaceholder
showAllPlaceholder: boolean
Type : boolean

Show "All" in combo trigger when all values are selected (@default: false)

tabIndex
tabIndex: number
Type : number

Tabulator click event order(@default:0)

valueKey
valueKey: string
Type : string

Value(relates to select options) identifier key (@default:identifier)

import {
  WidgetComponent,
  WidgetConfiguration,
  WidgetConfigure,
  WidgetInput,
  WidgetOutput,
} from "../widget.metadata";
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  TemplateRef,
  ViewChild,
} from "@angular/core";
import { getOrDefault, WidgetConfig } from "../widget.configuration";
import { BehaviorSubject, combineLatest, ReplaySubject, Subject } from "rxjs";
import { WidgetframeService } from "../widgetframe/widgetframe.service";
import {
  debounceTime,
  filter,
  flatMap,
  startWith,
  takeUntil,
} from "rxjs/operators";
import { NgUnsubscribe } from "../../ng-unsubscribe";
import { CurrentLocaleService } from "../../components/i18n";
import { notNullOrEmpty } from "../../components/util";
import {
  LocalStorageEntry,
  LocalStorageService,
} from "../../components/local-storage/local-storage.service";
import {
  DeletionMode,
  Scope,
} from "../../components/local-storage/local-storage-constants";

import { GroupByStrategy } from "../../components/combo/nm-combo.api";
import { NmComboComponent } from "../../components/combo/nm-combo.component";

interface SelectComboConfiguration {
  /**
   * Tabulator click event order(@default:0)
   */
  tabIndex: number;

  /**
   * Placeholder string to display
   */
  placeholder: string;

  /**
   * `true` to disable the component (@default:false)
   */
  disabled: boolean;

  /**
   * `true` to show the clear button (@default:true)
   */
  clearable: boolean;

  /**
   * Value(relates to select options) identifier key (@default:identifier)
   */
  valueKey: string;

  /**
   * Value(relates to select options) displayed description key (@default:description)
   */
  displayKey: string;

  /**
   * Open options on focus (example over tabulator) (@default:false)
   */
  openOnFocus: boolean;

  /**
   * Id string-array of preselected values(relates to select options) (identifiers)
   */
  preselectedValues: string[];

  /**
   * Allow a empty value as option (@default:true)
   */
  allowEmpty: boolean;

  /**
   * Identifier and name of this field
   */
  identifier: string;

  /**
   * Fetch options of the select element from a url.
   */
  optionsDataUrl: string;

  /**
   * The key of embedded options-data in response of optionsDataUrl
   */
  optionsDataKey: string;

  /**
   * Sets the custom css class
   */
  customClass: string;

  /**
   *   If the data contains groups, this field either contains the parent reference or the child options
   */
  groupKey: string;

  /**
   *  "nested", groupKey should contain an array of options, "parent-reference": child options reference the valueKey field of their parent
   */
  groupStrategy: GroupByStrategy;

  /**
   *  Allow multiple selection (@default: false)
   */
  multiple: boolean;

  /**
   *  Show "All" in combo trigger when all values are selected (@default: false)
   */
  showAllPlaceholder: boolean;
}

@WidgetComponent("nm-select-combo")
@Component({
  selector: "nm-select-combo",
  templateUrl: "./select-combo.component.html",
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SelectComboComponent {
  @WidgetConfiguration()
  public configuration: WidgetConfig<SelectComboConfiguration>;

  public _unsubscribe = NgUnsubscribe.create();
  public _optionsDataUrl: string;
  public _optionsDataKey: string;
  public _preselectedValues: string[];
  public _selectionLocalstorageEntry: LocalStorageEntry;
  public _allLocalstorageEntry: LocalStorageEntry;

  public identifier: string;
  public options: any[];
  public selectedValues: string[];
  public valueKey: string;
  public displayKey: string;
  public tabIndex: number;
  public openOnFocus: boolean;
  public clearable: boolean;
  public disabled: boolean;
  public allowEmpty: boolean;
  public filterPlaceholder: string;
  public placeholder: string;
  public customClass: string;
  public groupKey: string;
  public groupStrategy: GroupByStrategy;
  public multiple: boolean;
  public hide: boolean = false;
  public showAllPlaceholder: boolean;

  @WidgetInput("options-url")
  public optionsDataUrl = new BehaviorSubject<string>("");

  @WidgetInput("reload-options")
  public reload = new Subject();

  @WidgetInput("hide")
  public hideChannel = new Subject<boolean>();

  @WidgetInput()
  public resetToDefault = new Subject<any>();

  @WidgetOutput("option-selected")
  public valueChanged = new ReplaySubject<any>(1);

  @WidgetOutput("allSelected")
  public allSelected = new ReplaySubject<boolean>(1);

  @ViewChild("combo")
  public combo: NmComboComponent;

  constructor(
    protected _widgetframeService: WidgetframeService,
    protected _currentLocaleService: CurrentLocaleService,
    protected cdr: ChangeDetectorRef,
    protected localstorageService: LocalStorageService
  ) {}

  @WidgetConfigure()
  public configureWidget(
    configuration: WidgetConfig<SelectComboConfiguration>
  ) {
    this.valueKey = getOrDefault(
      configuration.configuration.valueKey,
      "identifier"
    );
    this.displayKey = getOrDefault(
      configuration.configuration.displayKey,
      "description"
    );
    this.tabIndex = getOrDefault(configuration.configuration.tabIndex, 0);
    this.openOnFocus = getOrDefault(
      configuration.configuration.openOnFocus,
      false
    );
    this.clearable = getOrDefault(configuration.configuration.clearable, true);
    this.disabled = getOrDefault(configuration.configuration.disabled, false);
    this._preselectedValues = getOrDefault(
      configuration.configuration.preselectedValues,
      []
    );
    // todo PIMCORE-6734 allow empty option
    this.allowEmpty = getOrDefault(
      configuration.configuration.allowEmpty,
      true
    );
    this.identifier = getOrDefault(
      configuration.configuration.identifier,
      "select-combo-field"
    );
    this.customClass = getOrDefault(
      configuration.configuration.customClass,
      ""
    );
    this.groupKey = configuration.configuration.groupKey;
    this.groupStrategy = configuration.configuration.groupStrategy;
    this.multiple = getOrDefault(configuration.configuration.multiple, false);

    this._optionsDataUrl = configuration.configuration.optionsDataUrl;
    this._optionsDataKey = configuration.configuration.optionsDataKey;
    this.placeholder = configuration.configuration.placeholder;
    this.showAllPlaceholder = configuration.configuration.showAllPlaceholder;

    if (this._optionsDataUrl && !this._optionsDataKey) {
      console.error(
        '"_optionsDataKey" for widget "',
        this.identifier,
        '" missing!'
      );
    }

    let localStorageKey = configuration.configuration["local-storage-key"];
    if (localStorageKey) {
      this._selectionLocalstorageEntry =
        this.localstorageService.getLocalStorageEntry(
          localStorageKey,
          Scope.USER,
          DeletionMode.RESET
        );
      if (this.showAllPlaceholder) {
        this._allLocalstorageEntry =
          this.localstorageService.getLocalStorageEntry(
            "allSelected-" + localStorageKey,
            Scope.USER,
            DeletionMode.RESET
          );
      }
    }

    combineLatest([
      this.optionsDataUrl.asObservable().pipe(
        startWith(this._optionsDataUrl),
        filter((url) => !!url)
      ),
      this._currentLocaleService.getCurrentLocale(),
      this.reload.asObservable().pipe(startWith(null)),
    ])
      .pipe(
        takeUntil(this._unsubscribe),
        debounceTime(50),
        flatMap((data) => {
          return this._widgetframeService.getData(this._optionsDataUrl);
        })
      )
      .subscribe((response) => {
        if (response) {
          this.options = response._embedded[this._optionsDataKey];
          this.setPreselectValues();
        }
      });

    this.hideChannel
      .asObservable()
      .pipe(takeUntil(this._unsubscribe))
      .subscribe((hide) => {
        this.hide = hide;
        this.cdr.detectChanges();
      });

    this.resetToDefault
      .asObservable()
      .pipe(takeUntil(this._unsubscribe))
      .subscribe((reset) => {
        this.selectedValues = [];
        if (this._selectionLocalstorageEntry) {
          this._selectionLocalstorageEntry.clear();
        }
        this.setPreselectValues();
        this.cdr.detectChanges();
      });
  }

  public onChange(value: any) {
    let _values = Array.isArray(value) ? value : [value];
    this.selectedValues = _values;
    this.valueChanged.next(_values);
    if (this._selectionLocalstorageEntry) {
      this._selectionLocalstorageEntry.value = JSON.stringify(_values);
    }
  }

  private setPreselectValues() {
    const flattened = this.combo._api.getFlatComboOptions(
      this.options,
      this.groupKey
    );
    // check for case @WidgetInput("options-url") changed and preselected value not exist in new options
    if (notNullOrEmpty(this.selectedValues)) {
      this.setValidSelectedValues(this.selectedValues, flattened);
    } else {
      if (notNullOrEmpty(this._preselectedValues)) {
        this.setValidSelectedValues(this._preselectedValues, flattened);
      } else if (
        this._selectionLocalstorageEntry &&
        this._selectionLocalstorageEntry.exists()
      ) {
        this.selectedValues = JSON.parse(
          this._selectionLocalstorageEntry.value
        );
      } else {
        this.selectedValues = flattened
          .filter((option) => option.default === true)
          .map((option) => option[this.valueKey]);
      }
    }

    this.isAllSelected(this.selectedValues.length === flattened.length);

    this.valueChanged.next(this.selectedValues);
    this.cdr.markForCheck();
  }

  private setValidSelectedValues(values: string[], options: any[]) {
    let optionValueIDs = options.map((option) => option[this.valueKey]);
    this.selectedValues = values.filter((valueId) =>
      optionValueIDs.includes(valueId)
    );
  }

  isAllSelected(allSelected) {
    this.allSelected.next(allSelected);
    if (this._allLocalstorageEntry) {
      this._allLocalstorageEntry.value = allSelected;
    }
  }
}

results matching ""

    No results matching ""