File

src/app/shared/widgets/buy/search/search.component.ts

Index

Properties

Properties

autofocus
autofocus: boolean
Type : boolean
Optional

Auto focus field.

disableSearchOnEmptyField
disableSearchOnEmptyField: boolean
Type : boolean
Optional

Enables/Disables searching with empty search term

enableListsearch
enableListsearch: boolean
Type : boolean
Optional

Enables/Disables the list search option

enableListSearchOnly
enableListSearchOnly: boolean
Type : boolean
Optional

Enables/Disables list search

enableTemplating
enableTemplating: boolean
Type : boolean
Optional

Enables/Disables using a template for the search and it's required for list search

freetext-search-on-button
freetext-search-on-button: boolean
Type : boolean
Optional

Enables freetext searching on button clicked @default(false)

freetext-search-on-enter
freetext-search-on-enter: boolean
Type : boolean
Optional

Enables freetext searching on enter clicked @default(true)

header
header: string
Type : string
Optional

Specifies the widget frame header type (default: primary)

infoText
infoText: string
Type : string
Optional

Sets info text to explain the widget freetext search functionality

infoText-listsearch
infoText-listsearch: string
Type : string
Optional

Sets info text to explain the widget list search functionality

links
links: any[]
Type : any[]
Optional

Sets link used for templating

list-search-on-input
list-search-on-input: boolean
Type : boolean
Optional

Enables list searching on input change @default(true)

localstorage-listsearch
localstorage-listsearch: string
Type : string
Optional

Sets local storage key name for the list search for saving the search term

localstorage-search
localstorage-search: string
Type : string
Optional

Sets local storage key name for saving the search term

placeholderkey
placeholderkey: string
Type : string
Optional

Sets the placeholder key for the search field @default(elasticsearch.search.paceholder)

removeListSearchButton
removeListSearchButton: boolean
Type : boolean
Optional

Sets label for the button removing the list search @default(false)

scope
scope: string
Type : string
Optional

Sets the scope of the widget to differenciate between local storage keys

searchValue
searchValue: boolean
Type : boolean
Optional

Enables setting the search term parameter to 'searchValue' instead of the 'q' default

startListSearchLabel
startListSearchLabel: string
Type : string
Optional

Sets label for the button starting the list search @default(searchlist.start)

subheader
subheader: string
Type : string
Optional

Sets subheader

title
title: string
Type : string
Optional

Sets title of the widget header in the freetext mode

title-listsearch
title-listsearch: string
Type : string
Optional

Sets title of the widget header in the list search mode

width
width: string
Type : string
Optional

Specifies the widget frame width

wikiLink
wikiLink: string
Type : string
Optional

Sets the link to the wiki documents to further explain the functionality

withBorder
withBorder: boolean
Type : boolean
Optional

Shows/Hides the widget frame border

withHeader
withHeader: boolean
Type : boolean
Optional

Specifies whether the widget should show the header or not @default(true)

import {
  combineLatest as observableCombineLatest,
  Subject,
  Observable,
  ReplaySubject,
  BehaviorSubject,
} from "rxjs";

import { distinctUntilChanged, filter, takeUntil } from "rxjs/operators";
import {
  AfterViewInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  OnInit,
  ViewChild,
  OnDestroy,
} from "@angular/core";
import { WidgetframeService } from "../../widgetframe/widgetframe.service";
import { WidgetConfig } from "../../widget.configuration";
import {
  WidgetComponent,
  WidgetConfiguration,
  WidgetConfigure,
  WidgetId,
  WidgetInput,
  WidgetOutput,
} from "../../widget.metadata";
import { FormBuilder, FormGroup } from "@angular/forms";
import { ListService } from "../../list/index";
import * as uriTemplates_ from "uri-templates";
import {
  DeletionMode,
  Scope,
} from "../../../components/local-storage/local-storage-constants";
import {
  LocalStorageEntry,
  LocalStorageService,
} from "../../../components/local-storage/local-storage.service";
import { getOrDefault } from "../../widget.configuration";
import { NgUnsubscribe } from "../../../ng-unsubscribe";

const uriTemplates = uriTemplates_;
export interface SearchWidgetConfiguration {
  /** Enables/Disables the list search  option */
  enableListsearch?: boolean;
  /** Enables/Disables list search */
  enableListSearchOnly?: boolean;
  /** Enables/Disables searching with empty search term */
  disableSearchOnEmptyField?: boolean;
  /** Enables/Disables using a template for the search and it's required for list search */
  enableTemplating?: boolean;
  /** Specifies whether the widget should show the header or not @default(true) */
  withHeader?: boolean;
  /** Sets the link to the wiki documents to further explain the functionality */
  wikiLink?: string;
  /** Sets link used for templating */
  links?: any[];
  /** Sets local storage key name for saving the search term */
  "localstorage-search"?: string;
  /** Sets the scope of the widget to differenciate between local storage keys */
  scope?: string;
  /** Sets local storage key name for the list search for saving the search term */
  "localstorage-listsearch"?: string;
  /** Sets the placeholder key for the search field @default(elasticsearch.search.paceholder) */
  placeholderkey?: string;
  /** Enables freetext searching on enter clicked @default(true) */
  "freetext-search-on-enter"?: boolean;
  /** Enables list searching on input change @default(true) */
  "list-search-on-input"?: boolean;
  /** Enables freetext searching on button clicked @default(false) */
  "freetext-search-on-button"?: boolean;
  /** Sets subheader */
  subheader?: string;
  /** Sets label for the button starting the list search @default(searchlist.start) */
  startListSearchLabel?: string;
  /** Sets label for the button removing the list search @default(false) */
  removeListSearchButton?: boolean;
  /** Enables setting the search term parameter to 'searchValue' instead of the 'q' default */
  searchValue?: boolean;
  /** Sets info text to explain the widget freetext search functionality */
  infoText?: string;
  /** Sets title of the widget header in the freetext mode */
  title?: string;
  /** Sets info text to explain the widget list search functionality */
  "infoText-listsearch"?: string;
  /** Sets title of the widget header in the list search mode */
  "title-listsearch"?: string;
  /** Shows/Hides the widget frame border */
  withBorder?: boolean;
  /** Specifies the widget frame header type (default: primary) */
  header?: string;
  /** Specifies the widget frame width */
  width?: string;
  /** Auto focus field. */
  autofocus?: boolean;
}
@WidgetComponent("nm-search")
@Component({
  selector: "nm-search",
  templateUrl: "./search.component.html",
  styleUrls: ["./search.component.scss"],

  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SearchWidgetComponent implements AfterViewInit, OnInit, OnDestroy {
  public cols: any[];
  private attributes: any;
  public inputLink: string;
  public wikiLink: string;
  public infotext: string;
  public title: string;
  public subheader: string;
  public inputLinklistSearch: string;
  public enableListsearch: boolean;
  public enableListSearchOnly: boolean;
  public enableTemplating: boolean = true;
  public withHeader: boolean = true;
  public freetextSearchOnEnter: boolean = true;
  public freetextSearchOnButton: boolean = false;
  public placeholderkey: string;
  public disableSearchOnEmptyField: boolean = false;
  public autofocus: boolean = false;
  private encodeLink: boolean = true;
  public removeListSearchButton: boolean;
  public startListSearchLabel: string;

  private localStorageIsListSearchEntry: LocalStorageEntry;
  private localStorageSearchEntry: LocalStorageEntry;
  private localStorageListSearchEntry: LocalStorageEntry;

  public hide: boolean = false;

  private unsubscribe = NgUnsubscribe.create();

  @WidgetConfiguration()
  public configuration: WidgetConfig<SearchWidgetConfiguration>;

  /**
   * If templating is enabled emits the url that can be used to fetch the list-search data (if in list-search mode), else uses inputLink and fills it with the current search
   */
  @WidgetOutput("uri")
  private uri: Subject<any> = new ReplaySubject<any>(1);

  /**
   * Emits the user input if templating is disabled and search mode is list
   */
  @WidgetOutput("listSearchOutput")
  private listSearchOutput: Subject<any> = new ReplaySubject<any>(1);

  /**
   * Emits the current search mode ('freeTextSearch' or 'listSearch')
   */
  @WidgetOutput("modeischanged")
  private modeIsChanged: Subject<any> = new ReplaySubject<any>(1);

  /**
   * Deprecated
   */
  @WidgetOutput("profile")
  private profile: Subject<any> = new ReplaySubject<any>(1);

  /**
   * Resets the search
   */
  @WidgetInput("reset")
  private resetChannel: Subject<any> = new Subject<any>();

  /**
   * Hides the search widget
   */
  @WidgetInput("hide")
  private hideChannel: Subject<any> = new Subject<any>();

  /**
   * Sets the value of the search-field and performs a search
   */
  @WidgetInput("set")
  private inputChannel: Subject<any> = new BehaviorSubject<any>(null);

  /**
   * Clears search term
   */
  @WidgetInput("cleartextsearch")
  private clearChannel: Subject<any> = new Subject<any>();

  /**
   * Emits every time a search is performed (meant to force a reset of category-search, which are often used in conjunction with this)
   */
  @WidgetOutput("clearcategorysearch")
  private clearCategorySearch: Subject<any> = new Subject<any>();

  /**
   * Triggers when return is pressed on the search field (if the mode is not list-search)
   */
  @WidgetOutput("returnPressed")
  private returnPressed: Subject<any> = new Subject<any>();

  /**
   * Emits the search term everytime it changes
   */
  @WidgetOutput("searchTerm")
  private searchTerm: Subject<any> = new Subject<any>();

  /**
   * Triggers saving the search input in the local storage
   */
  @WidgetInput("saveSearchTerm")
  private saveSearchTerm: Subject<any> = new Subject<any>();

  private storageValue: Subject<any> = new ReplaySubject<any>(1);

  /**
   * Emits data on list search input, if enableTemplating = true
   */
  @WidgetOutput("listSearchOnChangeOutput")
  private listSearchOnChangeOutput: Subject<any> = new ReplaySubject<any>(1);

  @WidgetId()
  public _id: string;

  @ViewChild("inputComponent") inputComponent;

  private sub;
  public searchform: FormGroup;
  public listsearch: boolean = false;

  constructor(
    private _widgetframeService: WidgetframeService,
    private formBuilder: FormBuilder,
    private _listService: ListService,
    private localStorageService: LocalStorageService,
    private _changeDetectorRef: ChangeDetectorRef
  ) {
    this.searchform = this.formBuilder.group({
      searchInput: "",
    });
  }

  setSearchTerm(value) {
    this.searchform.value.searchInput = value;
    if (this.localStorageListSearchEntry) {
      this.localStorageListSearchEntry.value = value;
    }
  }

  keyDownFunction(event) {
    if (this.freetextSearchOnEnter && !this.listsearch) {
      this.doFreetextSearch(this.searchform.value.searchInput);
      this.returnPressed.next(new Date());
      this._changeDetectorRef.markForCheck();
    }
  }

  onChange(event) {
    this.searchTerm.next(this.searchform.value.searchInput);
    if (!this.freetextSearchOnEnter && !this.freetextSearchOnButton) {
      this.doFreetextSearch(this.searchform.value.searchInput);
      this._changeDetectorRef.markForCheck();
    }
  }

  doListSearch(value) {
    this.clearCategorySearch.next(Date.now);
    if (this.localStorageListSearchEntry) {
      this.localStorageListSearchEntry.value = value;
    }

    this._changeDetectorRef.markForCheck();

    if (this.enableTemplating && this.encodeLink) {
      this._widgetframeService
        .postData(this.inputLinklistSearch, value)
        .subscribe((data) => {
          this.uri.next(data._links.results.href);
        });
    } else {
      this.listSearchOutput.next(value);
    }
  }

  doFreetextSearch(value) {
    this.clearCategorySearch.next(Date.now);
    if (this.localStorageSearchEntry) {
      this.localStorageSearchEntry.value = value;
    }
    if (this.enableTemplating && this.encodeLink) {
      let uriParams;
      if (this.configuration.configuration["searchValue"]) {
        uriParams = { searchValue: value };
      } else {
        uriParams = { q: value };
      }
      if (!(this.disableSearchOnEmptyField && uriParams["q"].length === 0)) {
        let link = uriTemplates(this.inputLink).fill(uriParams);
        this.uri.next(link);
      }
    } else {
      if (!(this.disableSearchOnEmptyField && value.length === 0)) {
        this.uri.next(value);
      }
    }
    this._changeDetectorRef.markForCheck();
  }

  toggleMode($event) {
    if ($event.checked) {
      this.switchToListSearch();
    } else {
      this.switchToFreetextSearch();
    }
  }

  private switchToFreetextSearch() {
    this.modeIsChanged.next("freeTextSearch");
    this.listsearch = false;
    this.localStorageIsListSearchEntry.value = "false";
    this.infotext = this.configuration.configuration["infoText"];
    this.title = this.configuration.configuration["title"];
    this.resetFromLocalStorage(this.localStorageSearchEntry);
  }

  private switchToListSearch() {
    this.modeIsChanged.next("listSearch");
    this.listsearch = true;
    this.localStorageIsListSearchEntry.value = "true";
    this.infotext = this.configuration.configuration["infoText-listsearch"];
    this.title = this.configuration.configuration["title-listsearch"];
    this.resetFromLocalStorage(this.localStorageListSearchEntry);
  }

  resetFromLocalStorage(entry: LocalStorageEntry) {
    if (entry) {
      let value = entry.value;
      this.storageValue.next(value);
      this.updateTextField(value);
    }
  }

  private updateTextField(value: string) {
    this.searchform.setValue({
      searchInput: value || "",
    });

    window.setTimeout(() => {
      this.searchform.patchValue({
        searchInput: value || "",
      });

      this._changeDetectorRef.markForCheck();
    }, 1);
  }

  doSearch(value) {
    this.updateTextField(value);
    if (this.listsearch || this.enableListSearchOnly) {
      this.doListSearch(value);
    } else {
      this.doFreetextSearch(value);
    }
  }

  onListValueChange(value) {
    this.listSearchOnChangeOutput.next(value);
    if (this.localStorageListSearchEntry && this.removeListSearchButton) {
      this.localStorageListSearchEntry.value = value;
    }
  }

  @WidgetConfigure()
  protected configureWidget(configuration: WidgetConfig) {
    this.enableListsearch = this.configuration.configuration[
      "enableListsearch"
    ];
    this.enableListSearchOnly = this.configuration.configuration[
      "enableListSearchOnly"
    ];
    this.disableSearchOnEmptyField = this.configuration.configuration[
      "disableSearchOnEmptyField"
    ];
    if (this.configuration.configuration["enableTemplating"] != undefined) {
      this.enableTemplating = this.configuration.configuration[
        "enableTemplating"
      ];
    }
    if (this.configuration.configuration["withHeader"] != undefined) {
      this.withHeader = this.configuration.configuration["withHeader"];
    }
    this.wikiLink = this.configuration.configuration["wikiLink"];
    if (this.configuration.configuration["links"]) {
      this.inputLink = this.configuration.configuration["links"]["search"];
      this.inputLinklistSearch = this.configuration.configuration["links"][
        "listSearch"
      ];
    }
    if (this.configuration.configuration["localstorage-search"]) {
      this.localStorageSearchEntry = this.localStorageService.getLocalStorageEntry(
        this.configuration.configuration["scope"] +
          this.configuration.configuration["localstorage-search"],
        Scope.GLOBAL,
        DeletionMode.RESET
      );
    }
    if (this.configuration.configuration["localstorage-listsearch"]) {
      this.localStorageListSearchEntry = this.localStorageService.getLocalStorageEntry(
        this.configuration.configuration["scope"] +
          this.configuration.configuration["localstorage-listsearch"],
        Scope.GLOBAL,
        DeletionMode.RESET
      );
    }

    this.localStorageIsListSearchEntry = this.localStorageService.getLocalStorageEntry(
      this.configuration.configuration["scope"] + "nm-product-listsearch",
      Scope.GLOBAL,
      DeletionMode.RESET
    );
    this.placeholderkey = this.configuration.configuration["placeholderkey"]
      ? this.configuration.configuration["placeholderkey"]
      : "elasticsearch.search.paceholder";
    this.freetextSearchOnEnter =
      this.configuration.configuration["freetext-search-on-enter"] !== undefined
        ? this.configuration.configuration["freetext-search-on-enter"]
        : true;
    this.encodeLink =
      this.configuration.configuration["list-search-on-input"] !== undefined
        ? this.configuration.configuration["list-search-on-input"]
        : true;
    this.freetextSearchOnButton =
      this.configuration.configuration["freetext-search-on-button"] !==
      undefined
        ? this.configuration.configuration["freetext-search-on-button"]
        : false;
    if (this.freetextSearchOnButton) {
      this.freetextSearchOnEnter = false;
    }
    this.withHeader =
      this.configuration.configuration["withHeader"] !== undefined
        ? this.configuration.configuration["withHeader"]
        : true;
    this.subheader =
      this.configuration.configuration["subheader"] !== undefined
        ? this.configuration.configuration["subheader"]
        : "";
    this.startListSearchLabel = getOrDefault(
      this.configuration.configuration["startListSearchLabel"],
      "searchlist.start"
    );
    this.removeListSearchButton = getOrDefault(
      this.configuration.configuration["removeListSearchButton"],
      false
    );
    this.autofocus = getOrDefault(
      this.configuration.configuration["autofocus"],
      false
    );

    if (
      this.localStorageIsListSearchEntry.exists() &&
      (this.enableListsearch || this.enableListSearchOnly)
    ) {
      this.listsearch =
        this.localStorageIsListSearchEntry.value === "true" ? true : false;
    }
    if (this.listsearch || this.enableListSearchOnly) {
      this.switchToListSearch();
    } else {
      this.switchToFreetextSearch();
    }

    this.resetChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((reset) => {
        this.searchform.value.searchInput = null;
        if (this.localStorageSearchEntry) {
          this.localStorageSearchEntry.clear();
        }
        if (this.localStorageListSearchEntry) {
          this.localStorageListSearchEntry.clear();
        }
        this.doSearch("");
        this._changeDetectorRef.markForCheck();
      });

    this.clearChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((reset) => {
        this.localStorageSearchEntry.clear();
        if (this.localStorageListSearchEntry) {
          this.localStorageListSearchEntry.clear();
        }
        this.updateTextField("");
        this._changeDetectorRef.markForCheck();
      });

    this.saveSearchTerm
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((save) => {
        this.localStorageSearchEntry.value = this.searchform.value.searchInput;
      });

    this.hideChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((hide) => {
        this.hide = hide;
      });
  }

  public ngOnInit() {
    observableCombineLatest(
      this.storageValue,
      this.inputChannel,
      (storage, input) => {
        if (input) {
          return input;
        }

        return storage;
      }
    )
      .pipe(
        filter((value) => value),
        distinctUntilChanged(),
        takeUntil(this.unsubscribe)
      )
      .subscribe((value) => this.doSearch(value));
  }

  ngAfterViewInit() {
    if (!this.listsearch) {
      this.searchTerm.next(this.searchform.value.searchInput);
    }
    if (this.inputComponent && this.inputComponent.first) {
      setTimeout(() => {
        this.inputComponent.first.nativeElement.focus();
        this._changeDetectorRef.markForCheck();
      }, 1);
    }
  }

  ngAfterViewChecked() {
    this._changeDetectorRef.markForCheck();
  }

  ngOnDestroy() {
    this.unsubscribe.destroy();
  }
}

results matching ""

    No results matching ""