@WidgetComponent

nm-list

File

src/app/shared/widgets/list/list.component.ts

Implements

OnInit OnDestroy

Metadata

host {
}
selector nm-list
styleUrls list.component.scss
templateUrl ./list.component.html

Index

Widget inputs
Widget outputs
Properties
Methods

Constructor

constructor(listService: ListService, router: Router, route: ActivatedRoute, _scrollService: ScrollService, _progressbarService: ProgressbarService, _shopCategoryService: ShopCategoryService, localStorageService: LocalStorageService, _notificationService: CustomNotificationService)
Parameters :
Name Type Optional
listService ListService no
router Router no
route ActivatedRoute no
_scrollService ScrollService no
_progressbarService ProgressbarService no
_shopCategoryService ShopCategoryService no
localStorageService LocalStorageService no
_notificationService CustomNotificationService no

Methods

Private addRowIndexToSelectedItem
addRowIndexToSelectedItem(item: any)
Parameters :
Name Type Optional
item any no
Returns : any
Protected configureWidget
configureWidget(configuration: WidgetConfig)
Decorators : WidgetConfigure

Available json configurations:

isListviewEnabled, cssClass, header, hideOnEmpty, default-profile, profiles, dataType, infoText, title, wikiLink, selectionMode

Parameters :
Name Type Optional
configuration WidgetConfig no
Returns : void
dropdownValueChanged
dropdownValueChanged(object: , rowIndex: )
Parameters :
Name Optional
object no
rowIndex no
Returns : void
Private emitResults
emitResults(object: )
Parameters :
Name Optional
object no
Returns : void
Private filterKey
filterKey(field: string, value: string)
Parameters :
Name Type Optional
field string no
value string no
Returns : string
getSortOrder
getSortOrder(col: )
Parameters :
Name Optional
col no
Returns : any
keydown
keydown(event: any)
Parameters :
Name Type Optional
event any no
Returns : void
keyup
keyup(event: any)
Parameters :
Name Type Optional
event any no
Returns : void
Public loadData
loadData(event: LazyLoadEvent)
Parameters :
Name Type Optional
event LazyLoadEvent no
Returns : void
Private mapField
mapField(value: any, type: string)
Parameters :
Name Type Optional
value any no
type string no
Returns : any
Private mapResult
mapResult(data: ResultResource)
Parameters :
Name Type Optional
data ResultResource no
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
onBlur
onBlur(data: )
Parameters :
Name Optional
data no
Returns : void
onChangeNumberField
onChangeNumberField(object: , rowIndex: )
Parameters :
Name Optional
object no
rowIndex no
Returns : void
onChangeViewMode
onChangeViewMode(event: )
Parameters :
Name Optional
event no
Returns : void
onEnter
onEnter(event: )
Parameters :
Name Optional
event no
Returns : void
onFilterKeyup
onFilterKeyup(value: , field: )
Parameters :
Name Optional
value no
field no
Returns : void
onFilterKeyupCustom
onFilterKeyupCustom(value: , field: , filterMatchMode: )
Parameters :
Name Optional
value no
field no
filterMatchMode no
Returns : void
onFocus
onFocus(data: )
Parameters :
Name Optional
data no
Returns : void
onPage
onPage(event: )
Parameters :
Name Optional
event no
Returns : void
onRowSelectChange
onRowSelectChange(event: )
Parameters :
Name Optional
event no
Returns : void
onSelect
onSelect(event: )
Parameters :
Name Optional
event no
Returns : void
onSelectionChange
onSelectionChange(event: )
Parameters :
Name Optional
event no
Returns : void
onSortingChanged
onSortingChanged(event: , col: )
Parameters :
Name Optional
event no
col no
Returns : void
openLink
openLink(data: , column: , event: )
Parameters :
Name Optional
data no
column no
event no
Returns : boolean
openRelation
openRelation(contentNo: )
Parameters :
Name Optional
contentNo no
Returns : void
openRoute
openRoute(data: , column: , event: )
Parameters :
Name Optional
data no
column no
event no
Returns : boolean
Public reload
reload(force: boolean)
Parameters :
Name Type Optional Default value
force boolean no false
Returns : void
Private restoreState
restoreState(lasturi: )
Parameters :
Name Optional
lasturi no
Returns : void
Private restoreStateForListview
restoreStateForListview(lasturi: )
Parameters :
Name Optional
lasturi no
Returns : void
selectors
selectors()
Returns : { content: string; target: string; }
showDetails
showDetails(path: )
Parameters :
Name Optional
path no
Returns : void
Public slideChange
slideChange(event: )
Parameters :
Name Optional
event no
Returns : void
toogleContentVisibility
toogleContentVisibility()
Returns : void

Properties

Private _uriParams
_uriParams: UriParams
Type : UriParams
Public autoexpand
autoexpand: boolean
Type : boolean
Default value : false
Private autoSearchLocalStorage
autoSearchLocalStorage: LocalStorageEntry
Type : LocalStorageEntry
Public boxHeight
boxHeight: string
Type : string
Default value : "220px"
Public boxWidth
boxWidth: string
Type : string
Default value : "33%"
Private clearSelectionChannel
clearSelectionChannel: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput

Resets all selected rows

Public clientPaging
clientPaging: boolean
Type : boolean
Default value : false
Public cols
cols: Subject<any[]>
Type : Subject<any[]>
Default value : new BehaviorSubject([])
Public columns
columns: literal type
Type : literal type
Default value : {}
Public configuration
configuration: WidgetConfig
Type : WidgetConfig
Decorators : WidgetConfiguration
Private contentNoLocalStorage
contentNoLocalStorage: LocalStorageEntry
Type : LocalStorageEntry
Public contentVisible
contentVisible: boolean
Type : boolean
Default value : true
Public cssClass
cssClass: string
Type : string
Private currentLink
currentLink: string
Type : string
datatable
datatable: any
Type : any
Decorators : ViewChild
Private dateOptions
dateOptions:
Default value : { year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", } as const
Public debounceTime
debounceTime: number
Type : number
Default value : 500
Public dropdownData
dropdownData: Subject<any[]>
Type : Subject<any[]>
Default value : new BehaviorSubject([])
Decorators : WidgetInput
Public dropdownsData
dropdownsData: literal type
Type : literal type
Default value : {}
Public editedRow
editedRow: any
Type : any
Default value : {}
Public expandedRows
expandedRows: any[]
Type : any[]
Default value : []
Public externalResource
externalResource: boolean
Type : boolean
Default value : false
Private filter
filter: string[]
Type : string[]
Public filterChanged
filterChanged: boolean
Type : boolean
Default value : false
Public filterOnBlur
filterOnBlur: boolean
Type : boolean
Default value : false
Public firstLoad
firstLoad: boolean
Type : boolean
Default value : true
Public header
header: string
Type : string
Public hideOnEmpty
hideOnEmpty: boolean
Type : boolean
Default value : false
Public hideTable
hideTable: Subject<any>
Type : Subject<any>
Default value : new ReplaySubject<any>()
Decorators : WidgetInput
Public input
input:
Default value : new Subject<any>()
Decorators : WidgetInput
Private inputChannel
inputChannel: ReplaySubject<any>
Type : ReplaySubject<any>
Default value : new ReplaySubject<any>()
Decorators : WidgetInput

The uri that should be used to fetch the data

Public isMultiselectActionNeeded
isMultiselectActionNeeded: boolean
Type : boolean
Default value : false
Public isViewmodeList
isViewmodeList: boolean
Type : boolean
Default value : false
Private isViewmodeListKey
isViewmodeListKey: string
Type : string
Private isViewmodeListLocalStorage
isViewmodeListLocalStorage: LocalStorageEntry
Type : LocalStorageEntry
Public keepSettingsAfterChangeViewMode
keepSettingsAfterChangeViewMode: boolean
Type : boolean
Default value : false
Public lastPrimeNGEvent
lastPrimeNGEvent: LazyLoadEvent
Type : LazyLoadEvent
Default value : {}
Public lasttotalresults
lasttotalresults: Result[]
Type : Result[]
Default value : []
Private lastUriLocalStorage
lastUriLocalStorage: LocalStorageEntry
Type : LocalStorageEntry
Public limit
limit: number
Type : number
Default value : 10
Public lookups
lookups: any
Type : any
Public mappedResults
mappedResults: Observable<Result[]>
Type : Observable<Result[]>
Private modeIsChangedChannel
modeIsChangedChannel: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput
Public multiselectaction
multiselectaction: Subject<any>
Type : Subject<any>
Default value : new BehaviorSubject({})
Public multiselectpayload
multiselectpayload: Subject<any>
Type : Subject<any>
Default value : new BehaviorSubject({})
Private offset
offset: number
Type : number
Private onChange
onChange: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Public onEdit
onEdit:
Default value : new Subject<any>()
Decorators : WidgetOutput

Emits each time a row is inline editted, payload is the editted row

Public profile
profile: string
Type : string
Private profileChannel
profileChannel: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput

Set the profile the table is using

Static QUERY_PARAMS_CONTD
QUERY_PARAMS_CONTD: string
Type : string
Default value : "{&page,offset,limit,filter*,sort,data-locale,locale,cache,attributes,force-reload}"
Static QUERY_PARAMS_PAGING_CONTD
QUERY_PARAMS_PAGING_CONTD: string
Type : string
Default value : "{&page,offset,limit}"
Static QUERY_PARAMS_PAGING_START
QUERY_PARAMS_PAGING_START: string
Type : string
Default value : "{?page,offset,limit}"
Static QUERY_PARAMS_START
QUERY_PARAMS_START: string
Type : string
Default value : "{?page,offset,limit,filter*,sort,data-locale,locale,cache,attributes,force-reload}"
Public refresh
refresh: any
Type : any
Public relation
relation: Subject<any>
Type : Subject<any>
Default value : new ReplaySubject<any>()
Decorators : WidgetOutput
Public relationURL
relationURL: string
Type : string
Private reloadChannel
reloadChannel: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput

Force a reload of the table on input

Private requestRunning
requestRunning:
Default value : false
Public requestStarted
requestStarted: boolean
Type : boolean
Default value : false
Public resetChannel
resetChannel:
Default value : new Subject<any>()
Decorators : WidgetInput

Reset the sort, filter and paginator// Emits all selected items whenever they change

Public results
results: Subject<Result[]>
Type : Subject<Result[]>
Default value : new BehaviorSubject([])
Decorators : WidgetOutput
Public searchLink
searchLink: BehaviorSubject<string>
Type : BehaviorSubject<string>
Default value : new BehaviorSubject<string>( null )
Decorators : WidgetOutput

Emits the link the list is searching for, each time a search is triggered

Private selectedItems
selectedItems: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetOutput

Emits all selected items whenever they change

Public selectedLocale
selectedLocale:
Default value : new ReplaySubject<any>()
Decorators : WidgetInput

Input for the current locale (of ipim)

Private selectedLocaleString
selectedLocaleString: string
Type : string
Default value : ""
Public selectedRows
selectedRows: Result[]
Type : Result[]
Default value : []
Public selectedRowsOnShift
selectedRowsOnShift: Result[]
Type : Result[]
Default value : []
Public selectedUiLocale
selectedUiLocale:
Default value : new ReplaySubject<any>()
Decorators : WidgetInput

Input for the current locale (of the ui)

Private selectedUiLocaleString
selectedUiLocaleString: string
Type : string
Default value : ""
Public selectedViewmode
selectedViewmode: string
Type : string
Default value : "table"
Public selectionMode
selectionMode: string
Type : string
Default value : "multiple"
Public shiftIsPressed
shiftIsPressed: boolean
Type : boolean
Public showProgressBar
showProgressBar:
Default value : new BehaviorSubject<boolean>(true)
Decorators : WidgetInput

Flag to toggle progress bar during request

Public slidevalue
slidevalue: number
Type : number
Default value : 3
Private sort
sort: string
Type : string
Private style
style: string
Type : string
Public template
template: any
Type : any
Public title
title: string
Type : string
Public total
total: BehaviorSubject<number>
Type : BehaviorSubject<number>
Default value : new BehaviorSubject(0)
Decorators : WidgetOutput
Public totalresults
totalresults: Result[]
Type : Result[]
Default value : []
Private unsubscribe
unsubscribe:
Default value : NgUnsubscribe.create()
Public wikiLink
wikiLink: string
Type : string
Public withFooter
withFooter: boolean
Type : boolean
Default value : false
Public withHeader
withHeader: boolean
Type : boolean
Default value : true

Accessors

uriParams
geturiParams()
seturiParams(params: any)
Parameters :
Name Type Optional
params any no
Returns : void
import {
  BehaviorSubject,
  empty as observableEmpty,
  Observable,
  of as observableOf,
  ReplaySubject,
  Subject,
  timer as observableTimer,
} from "rxjs";

import {
  catchError,
  debounceTime,
  distinctUntilChanged,
  map,
  mergeMap,
  switchMap,
  take,
  takeUntil,
  withLatestFrom,
} from "rxjs/operators";
import { Component, Input, OnDestroy, OnInit, ViewChild } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { Table } from "../../components/primeng/table/table";
import { LazyLoadEvent } from "../../components/primeng/common/lazyloadevent";

import { ListService } from "./list.service";
import { ScrollService } from "../../components/scroll/scroll.service";
import { ProgressbarService } from "../../components/progressbar/progressbar.service";
import { WidgetConfig } from "../widget.configuration";
import { ShopCategoryService } from "../apps/my-shop-md/shop-category/shop-category.service";
import { CustomNotificationService } from "../../components/notification/customnotification.service";
import { UtilService } from "../../components/util/util.service";
import {
  WidgetComponent,
  WidgetConfiguration,
  WidgetConfigure,
  WidgetInput,
  WidgetOutput,
} from "../widget.metadata";
import { Result, ResultResource } from "../interfaces/list.interfaces";
import { NgUnsubscribe } from "../../ng-unsubscribe";

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";

const uriTemplates = uriTemplates_;

declare var $;

declare var jQuery: any;

interface UriParams {
  timestamp?: number;
  template?: any;
  offset?: number;
  limit?: number;
  sort?: string;
  filter?: string[];

  [key: string]: any;
}

@WidgetComponent("nm-list")
@Component({
  selector: "nm-list",
  templateUrl: "./list.component.html",
  styleUrls: ["./list.component.scss"],
  host: {
    "(window:keydown.passive)": "keydown($event)",
    "(window:keyup.passive)": "keyup($event)",
  },
})
export class ListComponentWidget implements OnInit, OnDestroy {
  @ViewChild("dt") datatable: any;

  static QUERY_PARAMS_CONTD =
    "{&page,offset,limit,filter*,sort,data-locale,locale,cache,attributes,force-reload}";
  static QUERY_PARAMS_START =
    "{?page,offset,limit,filter*,sort,data-locale,locale,cache,attributes,force-reload}";

  static QUERY_PARAMS_PAGING_CONTD = "{&page,offset,limit}";
  static QUERY_PARAMS_PAGING_START = "{?page,offset,limit}";

  public selectedViewmode: string = "table";
  public isViewmodeList: boolean = false;
  public mappedResults: Observable<Result[]>;
  public multiselectaction: Subject<any> = new BehaviorSubject({});
  public multiselectpayload: Subject<any> = new BehaviorSubject({});
  public isMultiselectActionNeeded: boolean = false;

  public cols: Subject<any[]> = new BehaviorSubject([]);
  public lookups: any;

  public slidevalue: number = 3;
  public boxWidth: string = "33%";
  public boxHeight: string = "220px";
  public contentVisible: boolean = true;
  public totalresults: Result[] = [];
  public lasttotalresults: Result[] = [];
  public selectedRows: Result[] = [];
  public selectedRowsOnShift: Result[] = [];
  public expandedRows: any[] = [];
  public shiftIsPressed: boolean;
  public firstLoad: boolean = true;
  public externalResource: boolean = false;
  public clientPaging: boolean = false;
  public template: any;
  public profile: string;
  public hideOnEmpty: boolean = false;
  public autoexpand: boolean = false;
  public cssClass: string;
  public header: string;
  public filterChanged: boolean = false;
  public keepSettingsAfterChangeViewMode: boolean = false;
  public lastPrimeNGEvent: LazyLoadEvent = {};
  public refresh: any;
  public debounceTime: number = 500;
  public editedRow: any = {};
  public selectionMode = "multiple";
  public columns: { [key: string]: any } = {};
  public requestStarted: boolean = false;
  private requestRunning = false;
  public filterOnBlur: boolean = false;
  public withFooter: boolean = false;

  @WidgetInput()
  public dropdownData: Subject<any[]> = new BehaviorSubject([]);
  public dropdownsData: { [key: string]: any } = {};

  //Emits currently visible data
  @WidgetOutput("results")
  public results: Subject<Result[]> = new BehaviorSubject([]);

  @Input("widgetId") widgetId: string;

  @WidgetOutput("total")
  public total: BehaviorSubject<number> = new BehaviorSubject(0);

  @Input("info-text")
  public infoText: string = "list.results";
  public wikiLink: string;
  public title: string;

  @Input("inputLink") inputLink: string;

  @Input("dataType") dataType: string = "products";

  // Deprecated
  @WidgetInput()
  public input = new Subject<any>();

  /**
   * Emits each time a row is inline editted, payload is the editted row
   */
  @WidgetOutput("onEdit")
  public onEdit = new Subject<any>();

  @WidgetConfiguration()
  public configuration: WidgetConfig;

  /**
   * Emits the link the list is searching for, each time a search is triggered
   */
  @WidgetOutput("searchLink")
  public searchLink: BehaviorSubject<string> = new BehaviorSubject<string>(
    null
  );

  private _uriParams: UriParams;

  @Input("uriParams")
  public set uriParams(params: any) {
    this._uriParams = <UriParams>params;
  }

  public get uriParams(): any {
    return this._uriParams;
  }

  /**
   * The uri that should be used to fetch the data
   */
  @WidgetInput("uri")
  private inputChannel: ReplaySubject<any> = new ReplaySubject<any>();

  @WidgetInput("modeischanged")
  private modeIsChangedChannel: Subject<any> = new Subject<any>();

  /**
   * Force a reload of the table on input
   */
  @WidgetInput("reload")
  private reloadChannel: Subject<any> = new Subject<any>();

  /**
   * Reset the sort, filter and paginator// Emits all selected items whenever they change
   */
  @WidgetInput("reset")
  public resetChannel = new Subject<any>();

  /**
   *Resets all selected rows
   */
  @WidgetInput("clearSelection")
  private clearSelectionChannel: Subject<any> = new Subject<any>();

  /**
   *Set the profile the table is using
   */
  @WidgetInput("profile")
  private profileChannel: Subject<any> = new Subject<any>();

  /**
   *Emits all selected items whenever they change
   */
  @WidgetOutput("selectedItems")
  private selectedItems: Subject<any> = new Subject<any>();

  /**
   *Input for the current locale (of ipim)
   */
  @WidgetInput()
  public selectedLocale = new ReplaySubject<any>();

  /**
   *Input for the current locale (of the ui)
   */
  @WidgetInput()
  public selectedUiLocale = new ReplaySubject<any>();

  /**
   *Flag to toggle progress bar during request
   */
  @WidgetInput()
  public showProgressBar = new BehaviorSubject<boolean>(true);

  @WidgetOutput()
  public relation: Subject<any> = new ReplaySubject<any>();

  //  hide table
  @WidgetInput("hide")
  public hideTable: Subject<any> = new ReplaySubject<any>();

  private currentLink: string;

  private onChange: Subject<any> = new Subject<any>();

  private offset: number;
  public limit: number = 10;
  private sort: string;
  private filter: string[];
  private style: string;
  private isViewmodeListKey: string;
  public withHeader: boolean = true;

  private selectedLocaleString: string = "";
  private selectedUiLocaleString: string = "";
  private dateOptions = {
    year: "numeric",
    month: "numeric",
    day: "numeric",
    hour: "numeric",
    minute: "numeric",
  } as const;
  public relationURL: string;

  private isViewmodeListLocalStorage: LocalStorageEntry;
  private lastUriLocalStorage: LocalStorageEntry;
  private autoSearchLocalStorage: LocalStorageEntry;
  private contentNoLocalStorage: LocalStorageEntry;

  private unsubscribe = NgUnsubscribe.create();

  constructor(
    private listService: ListService,
    private router: Router,
    private route: ActivatedRoute,
    private _scrollService: ScrollService,
    private _progressbarService: ProgressbarService,
    private _shopCategoryService: ShopCategoryService,
    private localStorageService: LocalStorageService,
    private _notificationService: CustomNotificationService
  ) {
    //In case a former call was aborted
    this._progressbarService.requestFinished();
    this.selectedViewmode = "table";
    this.mappedResults = this.results.pipe(
      withLatestFrom(this.cols),
      map((data) => {
        const rows = data[0];
        const cols = data[1];

        if (cols.length == 0 || rows.length == 0) {
          return [];
        } else {
          return rows.map((input) => {
            const row = Object.assign({}, input);

            for (let i = 0; i < cols.length; i++) {
              const col = cols[i];
              const field = row[col.field];
              if (field == undefined) {
                continue;
              }
              if (col.type) {
                row[col.field] = this.mapField(field, col.type);
              }
            }

            return row;
          });
        }
      })
    );
  }

  /**
   *Available json configurations:
   *
   * isListviewEnabled, cssClass, header, hideOnEmpty, default-profile, profiles, dataType, infoText, title, wikiLink, selectionMode
   *
   */
  @WidgetConfigure()
  protected configureWidget(configuration: WidgetConfig) {
    this.title = this.configuration.configuration["title"];
    this.slidevalue = this.configuration.configuration["slidevalue"];

    this.lastUriLocalStorage = this.localStorageService.getLocalStorageEntry(
      "last-uri" + this.title,
      Scope.GLOBAL,
      DeletionMode.RESET
    );

    this.isViewmodeListKey =
      this.configuration.configuration["isViewmodeListKey"];
    this.isViewmodeListLocalStorage = this.isViewmodeListKey
      ? this.localStorageService.getLocalStorageEntry(
          this.isViewmodeListKey,
          Scope.GLOBAL,
          DeletionMode.LOGIN
        )
      : null;

    if (configuration.configuration["isListviewEnabled"]) {
      if (this.isViewmodeListLocalStorage.value) {
        this.isViewmodeList = this.isViewmodeListLocalStorage.value === "true";
      } else {
        this.isViewmodeList =
          this.configuration.configuration["isViewmodeListActive"];
      }
    }
    this.cssClass = configuration.configuration["cssClass"] || "";
    this.header = configuration.configuration["header"] || "primary";
    this.hideOnEmpty = configuration.configuration["hideOnEmpty"] || false;
    this.profile = configuration.configuration["default-profile"];
    this.cols.next(
      configuration.configuration["profiles"][
        configuration.configuration["default-profile"]
      ]
    );
    this.dataType = configuration.configuration["dataType"];
    this.infoText = configuration.configuration["infoText"];
    if (this.configuration.configuration["withHeader"] != undefined) {
      this.withHeader = this.configuration.configuration["withHeader"];
    }
    this.wikiLink = this.configuration.configuration["wikiLink"];
    const selectionMode = this.configuration.configuration["selectionMode"];
    if (selectionMode) {
      this.selectionMode = selectionMode;
    }
    this.dropdownData.next(
      configuration.configuration["dropdownConfigs"]
        ? configuration.configuration["dropdownConfigs"]
        : null
    );
    this.filterOnBlur = configuration.configuration["filterOnBlur"]
      ? configuration.configuration["filterOnBlur"]
      : false;
    this.withFooter = configuration.configuration["withFooter"]
      ? configuration.configuration["withFooter"]
      : false;
    this.externalResource = configuration.configuration["externalResource"];
    this.clientPaging =
      configuration.configuration["clientPaging"] !== undefined
        ? configuration.configuration["clientPaging"]
        : false;
    this.debounceTime =
      configuration.configuration["debounceTime"] !== undefined
        ? parseInt(configuration.configuration["debounceTime"])
        : 500;
    this.limit =
      this.configuration.configuration["defaultPageSize"] !== undefined
        ? parseInt(this.configuration.configuration["defaultPageSize"])
        : 10;
    this.autoexpand = configuration.configuration["autoexpand"]
      ? configuration.configuration["autoexpand"]
      : false;
    this.refresh = configuration.configuration["refresh"];
    this.relationURL = configuration.configuration["relationURL"]
      ? configuration.configuration["relationURL"]
      : "";

    if (this.refresh) {
      let timer = observableTimer(this.refresh, this.refresh);
      timer.pipe(takeUntil(this.unsubscribe)).subscribe((t) => {
        this.expandedRows = [].concat(this.datatable.expandedRows);
        //  this.reload(true);
      });
    }

    this.hideTable
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((hide) => {
        this.hideOnEmpty = true;
        this.results.next([]);
      });

    this.selectedLocale
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((selectedLocale) => {
        this.selectedLocaleString = selectedLocale;
        this.reload();
      });

    this.selectedUiLocale
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((selectedUiLocale) => {
        this.selectedUiLocaleString = selectedUiLocale;
        this.reload();
      });

    this.profileChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((profile) => {
        this.profile = profile;
        this.cols.next(configuration.configuration["profiles"][profile]);
      });

    this.clearSelectionChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((reload) => {
        this.selectedRows = [];
        this.isMultiselectActionNeeded = false;
      });

    this.reloadChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((reload) => {
        this.reload(true);
      });

    this.resetChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((reset) => {
        this.lastUriLocalStorage.clear();

        this.currentLink = null;
        this.lastPrimeNGEvent = {};
        this.lastPrimeNGEvent.filters = {};
        this.sort = "";
        this.filter = [];
        if (this.datatable) {
          this.datatable.reset();
        }
        this.inputChannel.next(null);
      });

    this.modeIsChangedChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((isChanged) => {
        if (this.datatable) {
          this.datatable.reset();
        }
        this.reload();
      });

    this.inputChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((link) => {
        console.log("input link", link);
        this.clearSelectionChannel.next();

        if (link === null || link === undefined) {
          this.total.next(null);
          this.results.next([]);
        } else {
          this._progressbarService.requestFinished();
          this.total.next(null);

          this.currentLink = link;
          let queryParams =
            link.indexOf("?") >= 0
              ? ListComponentWidget.QUERY_PARAMS_CONTD
              : ListComponentWidget.QUERY_PARAMS_START;
          this.currentLink =
            link.indexOf("filter*") >= 0 ? link : link + queryParams;
          this.offset = 0;
          this.totalresults = [];

          if (this.datatable) {
            this.datatable.reset();
          }
          this.lastPrimeNGEvent = {};
          this.lastPrimeNGEvent.filters = {};
          this.sort = "";
          this.filter = [];

          if (this.isViewmodeList) {
            this.results.next([]);
          }

          if (this.lastUriLocalStorage.exists() && this.firstLoad) {
            let lasturi = this.lastUriLocalStorage.value;
            let timer = observableTimer(1);
            timer.subscribe((t) => {
              if (this.datatable) {
                this.restoreState(lasturi);
              } else {
                this.restoreStateForListview(lasturi);
              }
              this.firstLoad = false;
            });
          } else {
            this.reload();
          }
        }
      });

    this.onChange
      .pipe(
        debounceTime(this.debounceTime),
        map((trigger) => {
          let input = this.currentLink;
          let offset = this.offset || 0;
          let limit = this.limit || 10;
          let sort = this.sort || "";
          let filter = this.filter || [];
          if (!input) {
            return null;
          }

          let uriParams = Object.assign({});
          if (!this.clientPaging) {
            uriParams.offset = offset;
            uriParams.limit = limit;
            uriParams.sort = sort;
            uriParams.filter = filter;
          }

          if (
            this.selectedLocaleString &&
            this.selectedLocaleString.length > 0
          ) {
            uriParams["data-locale"] = this.selectedLocaleString;
            this.dropdownData
              .pipe(takeUntil(this.unsubscribe), debounceTime(1), take(1))
              .subscribe((dropdownConfigs) => {
                if (dropdownConfigs != null) {
                  let dropdownData = {};
                  for (let dropdownConfig of dropdownConfigs) {
                    let template = uriTemplates(dropdownConfig.url).fill({
                      locale: this.selectedUiLocaleString
                        ? this.selectedUiLocaleString
                        : this.selectedLocaleString,
                    });
                    this.listService.getActions(template).subscribe((data) => {
                      let values = [];
                      let receivedValues: any[] =
                        data["_embedded"][dropdownConfig.dataType];
                      receivedValues.forEach((row) => {
                        values.push({
                          id: row.identifier,
                          description: row.description,
                        });
                      });
                      dropdownData[dropdownConfig.field] = values;
                      this.dropdownsData = dropdownData;
                    });
                  }
                }
              });
          }

          if (
            this.selectedUiLocaleString &&
            this.selectedUiLocaleString.length > 0
          ) {
            uriParams.locale = this.selectedUiLocaleString;
          }

          if (trigger !== undefined) {
            uriParams.cache = (<Date>trigger).getTime();
          }
          uriParams.template = input;
          return uriParams;
        }),
        map((uriParams) => {
          if (!uriParams) {
            return null;
          }
          this.template = uriTemplates((<any>uriParams).template);
          return this.template.fill(uriParams);
        }),
        switchMap((uri) => {
          this.requestRunning = true;
          if (this.requestStarted) {
            this.requestStarted = false;
            this._progressbarService.requestFinished();
          }
          this.searchLink.next(uri);
          return observableOf(uri).pipe(
            withLatestFrom(this.showProgressBar),
            mergeMap(([uri, showProgressBar]) => {
              if (uri && !uri.startsWith("undefined")) {
                this.lastUriLocalStorage.value = uri;
                if (this.externalResource) {
                  return this.listService.getTemplatedFilteredResults(uri);
                } else {
                  this.requestStarted = true;
                  return this.listService.getTemplatedFilteredResults(
                    uri,
                    showProgressBar
                  );
                }
              } else {
                return observableEmpty();
              }
            }),
            catchError((err) => {
              this._notificationService.fromResponse(err);
              this.requestRunning = false;
              return observableEmpty();
            })
          );
        }),
        takeUntil(this.unsubscribe)
      )
      .subscribe(
        (data) => {
          this.requestRunning = false;
          this.mapResult(data);
        },
        (err) => {
          this._progressbarService.requestFinished();
        }
      );

    this.cols
      .pipe(
        takeUntil(this.unsubscribe),
        map((cols) => {
          for (let col of cols) {
            if (!col.sortable && !col.filter) {
              if (col.style) {
                col.style += " noFilter";
              } else {
                col.style = "noFilter";
              }
            }
          }
          return cols;
        })
      )
      .subscribe((cols) => {
        let columns = {};
        for (let col of cols) {
          columns[col.field] = col;
        }
        this.columns = columns;
      });

    this.slideChange(null);
  }

  private restoreState(lasturi) {
    let params;
    if (!this.template) {
      params = UtilService.getAllUrlParams(lasturi);
    } else {
      params = this.template.fromUri(lasturi);
    }

    if (params === undefined) {
      return;
    }

    if (params.filter !== undefined) {
      for (var item of params.filter) {
        let filterIdentifier = item.substring(0, item.indexOf(":"));
        let filter = item.substring(
          item.indexOf('"') + 1,
          item.lastIndexOf('"')
        );
        this.datatable.filter(filter, filterIdentifier, "startsWith");

        var filterItem = this.filterKey(filterIdentifier, filter);
        this.lastPrimeNGEvent.filters[filterIdentifier] = {};
        this.lastPrimeNGEvent.filters[filterIdentifier].value = filter;
        this.filter.push(filterItem);
      }
    }
    if (params.sort !== undefined) {
      let item = params.sort;
      let sortIdentifier = item.substring(0, item.indexOf(":"));
      let sortValue = item.substring(item.indexOf(":") + 1, item.length);
      this.datatable.sortField = sortIdentifier;
      this.datatable.sortOrder = sortValue === "asc" ? 1 : -1;
      this.datatable.sortSingle();
      this.lastPrimeNGEvent.sortOrder = sortValue === "asc" ? 1 : -1;
      this.lastPrimeNGEvent.sortField = sortIdentifier;
      this.sort = params.sort;
    }

    if (params.offset !== undefined && params.offset != 0) {
      let paging = {
        first: parseInt(params.offset),
        rows: parseInt(params.limit),
      };
    }
    this.keepSettingsAfterChangeViewMode = true;
    this.reload();
  }

  private restoreStateForListview(lasturi) {
    this.lastPrimeNGEvent.filters = {};
    let params;

    if (!this.template) {
      params = UtilService.getAllUrlParams(lasturi);
    } else {
      params = this.template.fromUri(lasturi);
    }

    if (params === undefined) {
      return;
    }

    if (params.filter !== undefined) {
      for (var item of params.filter) {
        let filterIdentifier = item.substring(0, item.indexOf(":"));
        let filter = item.substring(
          item.indexOf('"') + 1,
          item.lastIndexOf('"')
        );
        var filterItem = this.filterKey(filterIdentifier, filter);
        this.lastPrimeNGEvent.filters[filterIdentifier] = {};
        this.lastPrimeNGEvent.filters[filterIdentifier].value = filter;
        this.filter.push(filterItem);
      }
    }

    if (params.sort !== undefined) {
      let item = params.sort;
      let sortIdentifier = item.substring(0, item.indexOf(":"));
      let sortValue = item.substring(item.indexOf(":") + 1, item.length);
      this.lastPrimeNGEvent.sortOrder = sortValue === "asc" ? 1 : -1;
      this.lastPrimeNGEvent.sortField = sortIdentifier;
      this.sort = params.sort;
    }

    this.keepSettingsAfterChangeViewMode = true;
    this.limit = 10;
    this.offset = 0;
    this.results.next([]);
    this.reload();
  }

  onFilterKeyupCustom(value, field, filterMatchMode) {
    let changed: boolean = false;
    for (let i = this.filter.length - 1; i >= 0; i--) {
      let item = this.filter[i];
      let split = item.split(":");

      if (split[0] && split[1] && split[0] === field && split[1] != value) {
        changed = true;
        if (!value) {
          this.filter.splice(i, 1);
        } else {
          split[1] = value;
          let join = split.join(":");
          this.filter[i] = join;
        }
      }
    }
    if (this.filter.length === 0 && field && value) {
      changed = true;
      this.filter.push(field + ":" + value);
    }
    if (changed) {
      this.lastUriLocalStorage.clear();
      this.firstLoad = false;
      this.reload();
    }
  }

  onFilterKeyup(value, field) {
    this.lastPrimeNGEvent.filters[field] = {};
    this.lastPrimeNGEvent.filters[field].value = value;

    let duplicate = this.filter.filter((item) => item.startsWith(field));
    if (duplicate.length > 0) {
      this.filter.splice(this.filter.indexOf(duplicate[0]), 1);
    }

    this.filter.push(this.filterKey(field, value));
    this.results.next([]);
    this.limit = 10;
    this.offset = 0;
    this.filterChanged = true;
    this.reload();
  }

  getSortOrder(col) {
    if (this.lastPrimeNGEvent.sortField == col.field) {
      return this.lastPrimeNGEvent.sortOrder;
    }
  }

  onSortingChanged(event, col) {
    if (event.target.classList.contains("fa-sort-desc")) {
      event.target.classList.remove("fa-sort-desc");
      event.target.classList.add("fa-sort-asc");
      this.lastPrimeNGEvent.sortOrder = 1;
    } else if (event.target.classList.contains("fa-sort-asc")) {
      event.target.classList.remove("fa-sort-asc");
      event.target.classList.add("fa-sort-desc");

      this.lastPrimeNGEvent.sortOrder = -1;
    } else {
      event.target.classList.add("fa-sort-desc");
      this.lastPrimeNGEvent.sortOrder = -1;
    }

    this.lastPrimeNGEvent.sortField = col.field;
    this.keepSettingsAfterChangeViewMode = true;
    var order = this.lastPrimeNGEvent.sortOrder === 1 ? "asc" : "desc";
    this.sort = this.lastPrimeNGEvent.sortField.toString() + ":" + order;
    this.limit = 10;
    this.offset = 0;
    this.results.next([]);
    this.reload();
  }

  ngOnInit() {
    this.lastPrimeNGEvent = {};
    this.lastPrimeNGEvent.filters = {};
    this._scrollService
      .getOnScroll()
      .pipe(debounceTime(200), takeUntil(this.unsubscribe))
      .subscribe((data) => {
        if (this._progressbarService.hasOpenRequests()) {
          return;
        }
        if (!this.isViewmodeList) {
          return;
        }
        let total = this.total.getValue();
        if (total < 10 || this.offset > total) {
          return;
        }
        this.offset = this.offset + 10;
        this.reload();
      });
  }

  ngOnDestroy(): void {
    this.unsubscribe.destroy();
    this._progressbarService.requestFinished();
  }

  onChangeViewMode(event) {
    this.totalresults = [];
    this.isViewmodeList = event.checked;
    this.isViewmodeListLocalStorage.value =
      this.isViewmodeList === true ? "true" : "false";
    this.keepSettingsAfterChangeViewMode = true;
    this.offset = 0;
    if (!this.isViewmodeList) {
      this.limit =
        this.configuration.configuration["defaultPageSize"] !== undefined
          ? parseInt(this.configuration.configuration["defaultPageSize"])
          : 10;
      let timer = observableTimer(1);
      timer.subscribe((t) => {
        if (this.lastUriLocalStorage.value) {
          this.restoreState(this.lastUriLocalStorage.value);
        }
      });
    } else {
      this.results.next([]);
      this.limit = 10;
      this.offset = 0;
      this.reload();
    }
  }

  private filterKey(field: string, value: string) {
    let filterType = this.columns[field]["filter-type"] || "";
    return (
      field + ":" + (filterType ? `${filterType}:` : "") + '"' + value + '"'
    );
  }

  public loadData(event: LazyLoadEvent) {
    var _sort: string = "";
    var _filter: string[] = [];
    if (!this.isViewmodeList) {
      this.lastPrimeNGEvent = event;
    }
    if (typeof event.sortField !== "undefined" && event.sortField !== null) {
      var order = event.sortOrder === 1 ? "asc" : "desc";
      _sort = event.sortField.toString() + ":" + order;
    }
    if (typeof event.filters !== "undefined" && event.filters !== null) {
      for (let field in event.filters) {
        _filter.push(this.filterKey(field, event.filters[field].value));
      }
    }
    if (!this.keepSettingsAfterChangeViewMode) {
      this.sort = _sort;
      this.filter = _filter;
      this.offset = event.first;
      this.limit = event.rows;
    }
    this.keepSettingsAfterChangeViewMode = false;
    this.reload();
  }

  public reload(force: boolean = false) {
    if (force) {
      this.onChange.next(new Date());
    } else {
      this.onChange.next();
    }
  }

  private mapResult(data: ResultResource) {
    //if there are additional attributes
    if (data._embedded[this.dataType][0]) {
      if (data._embedded[this.dataType][0].hasOwnProperty("attributes")) {
        for (var result of data._embedded[this.dataType]) {
          for (var attribute of result.attributes) {
            result[attribute.identifier] = attribute.value;
          }
        }
      }
      if (data._embedded[this.dataType][0].hasOwnProperty("properties")) {
        for (var result of data._embedded[this.dataType]) {
          for (var property of result.properties) {
            result[property.identifier] = property.value;
          }
        }
      }
    }

    this.lookups = data["lookups"];
    this.multiselectaction.next(data._actions);

    if (data._embedded[this.dataType].length > 0) {
      if (this.isViewmodeList) {
        if (this.slidevalue > 3) {
          if (this.offset === 0) {
            this.offset += 10;
            this.reload();
          } else if (this.slidevalue > 4 && this.offset < 20) {
            this.offset += 10;
            this.reload();
          }
        }
        if (this.filterChanged) {
          this.results.next(data._embedded[this.dataType]);
          this.filterChanged = false;
        } else {
          if (this.totalresults.length === 0) {
            this.results.subscribe((data) => {
              this.totalresults = data;
            });
          }
          this.totalresults = this.totalresults.concat(
            data._embedded[this.dataType]
          );
          this.results.next(this.totalresults);
        }
      } else {
        this.totalresults = data._embedded[this.dataType];
        this.results.next(data._embedded[this.dataType]);
      }
    } else if (!this.isViewmodeList) {
      this.results.next([]);
    }
    this.total.next(data.total);
    if (this.clientPaging) {
      this.total.next(data._embedded[this.dataType].length);
    }

    if (this.refresh) {
      this.datatable.expandedRows = [];

      if (this.autoexpand) {
        for (let index = 0; index < this.totalresults.length; index++) {
          if (
            this.lasttotalresults.length > 0 &&
            this.lasttotalresults[index]
          ) {
            if (
              this.lasttotalresults[index]["status"] !==
              this.totalresults[index]["status"]
            ) {
              this.expandedRows.push(this.totalresults[index]);
            }
          }
        }

        if (this.totalresults[0]) {
          if (
            this.totalresults[0]["status"] === "COMPLETED" &&
            this.offset === 0 &&
            this.filter.length === 0
          ) {
            this.expandedRows.push(this.totalresults[0]);
          }
        }
      }
      for (const row of this.expandedRows) {
        let rowtoAdd = this.totalresults.filter(
          (item) => item.identifier === row.identifier
        );
        if (rowtoAdd.length > 0) {
          this.datatable.expandedRows.push(rowtoAdd[0]);
        }
      }
    }
    // TODO: This leads to lost parameters
    // this.currentLink = data._links["custom"].href;

    this.lasttotalresults = this.totalresults;
  }

  onPage(event) {
    this.limit = event.rows;
    this.offset = event.first;
  }

  showDetails(path) {
    this.router.navigate(path, { relativeTo: this.route });
  }

  openLink(data, column, event) {
    event.stopPropagation();
    const template = uriTemplates(column.linkTemplate);
    const url = template.fill(data);
    if (column.openLinkInSameTab) {
      window.location.href = url;
    } else {
      window.open(url);
    }
    return false;
  }

  openRoute(data, column, event) {
    event.stopPropagation();
    const template = uriTemplates(column.linkTemplate);
    const url = template.fill(data);

    this.router.navigate([url]);
    return false;
  }

  openRelation(contentNo) {
    this.autoSearchLocalStorage = this.localStorageService.getLocalStorageEntry(
      "autoSearch",
      Scope.GLOBAL,
      DeletionMode.LOGIN
    );
    this.contentNoLocalStorage = this.localStorageService.getLocalStorageEntry(
      "content-searchInput",
      Scope.GLOBAL,
      DeletionMode.LOGIN
    );

    this.autoSearchLocalStorage.value = "true";
    this.contentNoLocalStorage.value = contentNo;

    this.showDetails([this.relationURL]);
    this.relation.next(contentNo);
  }

  onSelect(event) {}

  keydown(event: any) {
    if (event.keyCode === 16) {
      this.shiftIsPressed = true;
      this.selectedRowsOnShift = this.selectedRows;
    }
  }

  keyup(event: any) {
    if (event.keyCode === 16) {
      this.shiftIsPressed = false;
    }
  }

  onSelectionChange(event) {
    if (Array.isArray(event)) {
      this.selectedRows = event;
    } else {
      event = this.addRowIndexToSelectedItem(event);
      this.selectedRows = [event];
    }
  }

  onRowSelectChange(event) {
    this.selectedItems.next(this.selectedRows);
    let selectedRowsOnShiftIndexes = [];
    let selectedRowsIndex;
    let selectedRowsOnShiftIndexesMin;
    let selectedRowsOnShiftIndexesMax;
    let fromIndex;
    let toIndex;

    if (this.shiftIsPressed) {
      this.results.subscribe((allrows) => {
        allrows.forEach((row, index) => {
          this.selectedRowsOnShift.forEach((selectedRow, selectedRowindex) => {
            if (row.identifier === selectedRow.identifier) {
              selectedRowsOnShiftIndexes.push(index);
            }
          });
          if (row.identifier === this.selectedRows[0].identifier) {
            selectedRowsIndex = index;
          }
        });

        selectedRowsOnShiftIndexesMin = Math.min.apply(
          Math,
          selectedRowsOnShiftIndexes
        );
        selectedRowsOnShiftIndexesMax = Math.max.apply(
          Math,
          selectedRowsOnShiftIndexes
        );

        if (selectedRowsIndex < selectedRowsOnShiftIndexesMin) {
          fromIndex = selectedRowsIndex;
          toIndex = selectedRowsOnShiftIndexesMax;
        } else if (selectedRowsIndex > selectedRowsOnShiftIndexesMax) {
          fromIndex = selectedRowsOnShiftIndexesMin;
          toIndex = selectedRowsIndex;
        }

        allrows.forEach((row, index) => {
          if (fromIndex <= index && toIndex >= index) {
            this.selectedRows.push(row);
            this.selectedItems.next(this.selectedRows);
          }
        });
      });
    }

    if (this.selectedRows.length > 1) {
      this.isMultiselectActionNeeded = true;
    }
    let payload = [];
    this.selectedRows.forEach((row) => {
      if (row) {
        payload.push(row.identifier);
      }
    });
    this.multiselectpayload.next(payload);
  }

  toogleContentVisibility() {
    this.contentVisible = !this.contentVisible;
  }

  public slideChange(event) {
    if (this.slidevalue == 1) {
      this.boxWidth = "100%";
      this.boxHeight = "600px";
    } else if (this.slidevalue == 2) {
      this.boxWidth = "47%";
      this.boxHeight = "350px";
    } else if (this.slidevalue == 3) {
      this.boxWidth = "30%";
      this.boxHeight = "220px";
    } else if (this.slidevalue == 4) {
      this.boxWidth = "23%";
      this.boxHeight = "190px";
    } else if (this.slidevalue == 5) {
      this.boxWidth = "19%";
      this.boxHeight = "130px";
    }
    // Prevent reload if a request is already started, map result will handle reloading if the slide value is high enough
    if (this.slidevalue > 3 && !this.requestRunning) {
      if (this.offset === 0) {
        this.offset += 10;
        this.reload();
      } else if (this.slidevalue === 5 && this.offset === 10) {
        this.offset += 10;
        this.reload();
      }
    }
  }

  private mapField(value: any, type: string): any {
    switch (type) {
      case "date":
        return value.substring(0, 10);
      case "datetime":
        if (!value) {
          return;
        }

        const date = new Date(value);
        return date.toLocaleDateString(
          this.selectedLocaleString,
          this.dateOptions
        );
      default:
        return value;
    }
  }

  private addRowIndexToSelectedItem(item: any) {
    this.results.subscribe((allRows) => {
      allRows.forEach((row, index) => {
        if (item && row.identifier === item.identifier) {
          item["rowIndex"] = index;
        }
      });
    });
    return item;
  }

  onBlur(data) {
    this.editedRow["value"] = data;
    this.onEdit.next(this.editedRow);
  }

  onEnter(event) {
    event.target.blur();
  }

  onFocus(data) {
    this.editedRow = {};
    this.editedRow["originalValue"] = jQuery.extend(true, {}, data);
  }

  selectors() {
    return { content: this.dataType, target: "nm-list-row" };
  }

  dropdownValueChanged(object, rowIndex) {
    object["rowIndex"] = rowIndex;
    this.onEdit.next(object);
    this.emitResults(object);
  }

  onChangeNumberField(object, rowIndex) {
    object["rowIndex"] = rowIndex;
    this.onEdit.next(object);
    this.emitResults(object);
  }

  private emitResults(object) {
    let currentResults = [];

    this.results
      .pipe(
        map((data) => {
          data[object["rowIndex"]] = object;
          return data;
        })
      )
      .subscribe((data) => (currentResults = data));

    if (this.selectedRows.length > 0) {
      this.selectedItems.next(this.selectedRows);
    }
  }
}
<nm-widgetframe
  [configuration]="configuration"
  [infoText]="infoText"
  [infoTitle]="title"
  [wikiLink]="wikiLink"
  [visible]="!(hideOnEmpty && (results | async)?.length == 0)"
>
  <div slot="title" class="nm-widgetframe__title">
    <span>{{ title | translate }}</span>
    <span *ngIf="total | async as totalValue"> &nbsp;({{ totalValue }}) </span>

    <!-- This fills the remaining space of the current row -->
    <div class="u-flex-1"></div>
    <mat-slider
      class="nm-button__slider"
      color="primary"
      min="1"
      max="5"
      *ngIf="isViewmodeList"
      slidevalue
      [(ngModel)]="slidevalue"
      (change)="slideChange($event)"
    ></mat-slider>

    <p-toggleButton
      *ngIf="configuration.configuration['isListviewEnabled']"
      [(ngModel)]="isViewmodeList"
      (onChange)="onChangeViewMode($event)"
      offIcon="fa fa-table"
      onIcon="fa fa-list"
      popover="{{ 'table.switchview' | translate }}"
      offLabel=""
      onLabel=""
    ></p-toggleButton>
  </div>
  <div slot="content" class="nm-widgetframe__content">
    <div class="nm-list {{ dataType }} {{ cssClass }}">
      <p-dataTable
        (selectionChange)="onSelectionChange($event)"
        [value]="mappedResults | async"
        expandableRows="configuration.configuration['expandableRows']"
        emptyMessage="{{ 'table.emptytext.product' | translate }}"
        (onPage)="onPage($event)"
        (onLazyLoad)="loadData($event)"
        [paginator]="(mappedResults | async).length > 0"
        [rows]="limit"
        [pageLinks]="5"
        [lazy]="!clientPaging"
        [totalRecords]="total | async"
        [rowsPerPageOptions]="[5, 10, 25, 50, 100]"
        *ngIf="!isViewmodeList"
        [selectionMode]="selectionMode"
        (onRowSelect)="onRowSelectChange($event)"
        (onRowUnselect)="onRowSelectChange($event)"
        #dt
      >
        <ng-template let-result pTemplate="rowexpansion">
          <div class="nm-downloadlist">
            <nm-action-link-list [actions]="result._actions.download">
            </nm-action-link-list>
          </div>
        </ng-template>

        <p-column
          expander="true"
          *ngIf="configuration.configuration['expandableRows']"
        >
        </p-column>
        <p-column
          *ngFor="let column of cols | async"
          [sortable]="column.sortable"
          [filter]="column.filter"
          [field]="column.field"
          [header]="column.header | translate"
          [styleClass]="column.style"
          [editable]="column.editable"
          filterMatchMode="contains"
        >
          <ng-template pTemplate="editor" let-col let-data="rowData">
            <input
              type="text"
              [(ngModel)]="data[col.field]"
              (focus)="onFocus(data)"
              (blur)="onBlur(data)"
              (keydown.enter)="onEnter($event)"
              class="input-editor"
            />
          </ng-template>
          <ng-template pTemplate="filter" let-col *ngIf="column.filter">
            <mat-form-field *ngIf="filterOnBlur == false">
              <input
                pinputtext
                matInput
                placeholder="{{ col.header }}"
                [value]="
                  dt.filters[col.field] ? dt.filters[col.field].value : ''
                "
                type="text"
                class="ui-column-filter"
                *ngIf="col.filter == true"
                (click)="dt.onFilterInputClick($event)"
                (input)="
                  dt.onFilterKeyup(
                    $event.target.value,
                    col.field,
                    col.filterMatchMode
                  );
                  onFilterKeyupCustom(
                    $event.target.value,
                    col.field,
                    col.filterMatchMode
                  )
                "
              />
            </mat-form-field>
            <mat-form-field *ngIf="filterOnBlur == true">
              <input
                pinputtext
                matInput
                placeholder="{{ col.header }}"
                [value]="
                  dt.filters[col.field] ? dt.filters[col.field].value : ''
                "
                type="text"
                class="ui-column-filter"
                *ngIf="col.filter == true"
                (click)="dt.onFilterInputClick($event)"
                (blur)="
                  dt.onFilterKeyup(
                    $event.target.value,
                    col.field,
                    col.filterMatchMode
                  )
                "
              />
            </mat-form-field>
          </ng-template>

          <ng-template
            *ngIf="!externalResource"
            let-col
            let-results="rowData"
            let-rowIndex="rowIndex"
            pTemplate="body"
          >
            <ng-container [ngSwitch]="column.dataType">
              <div
                *ngSwitchCase="'route'"
                (id)="(results[col.field])"
                style="width: 100%"
                class="table-content"
              >
                <a (click)="openRoute(results, column, $event)">
                  <nm-ellipsis [content]="results[col.field]"></nm-ellipsis>
                </a>
              </div>
              <div
                *ngSwitchCase="'link'"
                (id)="(results[col.field])"
                style="width: 100%"
                class="table-content"
              >
                <a (click)="openLink(results, column, $event)">
                  <nm-ellipsis [content]="results[col.field]"></nm-ellipsis>
                </a>
              </div>
              <div
                *ngSwitchCase="'traffic-light'"
                (id)="(results[col.field])"
                style="width: 100%"
                class="table-content"
              >
                <div
                  class="traffic_light_single_container"
                  matTooltip="{{
                    column['tooltip-prefix'] + results[col.field] | translate
                  }}"
                >
                  <div class="traffic_light traffic_light_grid single">
                    <span class="active" [ngClass]="results[col.field]"></span>
                  </div>
                </div>
              </div>
              <div
                *ngSwitchDefault
                (id)="(results[col.field])"
                style="width: 100%"
                class="table-content"
              >
                <div
                  (id)="(results[col.field])"
                  style="width: 100%"
                  class="table-content"
                >
                  <div [ngSwitch]="col.field">
                    <div *ngSwitchCase="'main-asset'">
                      <nm-image
                        [container]="results"
                        asset="main-asset"
                        size="thumbnail"
                        width="auto"
                        height="auto"
                        max-width="48px"
                        max-height="48px"
                        tooltip="true"
                      ></nm-image>
                    </div>

                    <div *ngSwitchCase="'identifier'">
                      <div
                        class="nm-break"
                        *ngIf="
                          dataType != 'products' &&
                          dataType != 'assets' &&
                          dataType != 'variants' &&
                          dataType != 'content-text' &&
                          dataType != 'content-relations'
                        "
                      >
                        <nm-ellipsis
                          [content]="results[col.field]"
                        ></nm-ellipsis>
                      </div>

                      <div
                        *ngIf="dataType == 'products' || dataType == 'assets'"
                      >
                        <a
                          *ngIf="profile !== 'content-assets'"
                          [routerLink]="[
                            this.dataType.substring(
                              0,
                              this.dataType.length - 1
                            ),
                            results.identifier
                          ]"
                        >
                          <nm-ellipsis
                            [content]="results[col.field]"
                          ></nm-ellipsis>
                        </a>
                        <nm-ellipsis
                          *ngIf="profile === 'content-assets'"
                          [content]="results[col.field]"
                        ></nm-ellipsis>
                      </div>

                      <div *ngIf="dataType == 'variants'">
                        <a
                          (click)="
                            showDetails([this.dataType, results.identifier])
                          "
                        >
                          <nm-ellipsis
                            [content]="results[col.field]"
                          ></nm-ellipsis>
                        </a>
                      </div>

                      <div *ngIf="dataType == 'content-relations'">
                        <a (click)="openRelation(results.identifier)">
                          <nm-ellipsis
                            [content]="results[col.field]"
                          ></nm-ellipsis>
                        </a>
                      </div>

                      <div *ngIf="dataType == 'content-text'">
                        <mat-form-field class="editable-field">
                          <mat-select
                            [value]="results[col.field]"
                            name="editable-type"
                            [(ngModel)]="results[col.field]"
                            (selectionChange)="
                              dropdownValueChanged(results, rowIndex)
                            "
                          >
                            <mat-option
                              *ngFor="let data of dropdownsData[col.field]"
                              [value]="data.id"
                            >
                              {{ data.description }}
                            </mat-option>
                          </mat-select>
                        </mat-form-field>
                      </div>
                    </div>

                    <div *ngSwitchCase="'link'" class="nm-actions">
                      <ng-container
                        *ngFor="let act of results._actions | iterable"
                      >
                        <nm-action-icon
                          *ngIf="act.key != 'download'"
                          [action]="act.value"
                          [name]="act.key"
                        >
                        </nm-action-icon>
                      </ng-container>
                    </div>

                    <div *ngSwitchCase="'status'">
                      <div
                        *ngIf="results[col.field] == 'PROCESSING'"
                        class="nm-download-result-processing"
                      >
                        {{ results[col.field] | translate }}
                      </div>
                      <div
                        *ngIf="results[col.field] == 'COMPLETED'"
                        class="nm-download-result-completed"
                      >
                        {{ results[col.field] | translate }}
                      </div>
                      <div
                        *ngIf="results[col.field] == 'FAILED'"
                        class="nm-download-result-failed"
                      >
                        {{ results[col.field] | translate }}
                      </div>
                      <div
                        *ngIf="results[col.field] == 'TIMEOUT'"
                        class="nm-download-result-timeout"
                      >
                        {{ results[col.field] | translate }}
                      </div>
                    </div>

                    <div *ngSwitchCase="'status1'">
                      <div class="traffic_light traffic_light_grid single">
                        <span class="{{ results[col.field] }} active"></span>
                      </div>
                    </div>

                    <div *ngSwitchCase="'status2'">
                      <div class="traffic_light traffic_light_grid single">
                        <span class="{{ results[col.field] }} active"></span>
                      </div>
                    </div>

                    <div *ngSwitchCase="'status3'">
                      <div class="traffic_light traffic_light_grid single">
                        <span class="{{ results[col.field] }} active"></span>
                      </div>
                    </div>

                    <div *ngSwitchCase="'status4'">
                      <div class="traffic_light traffic_light_grid single">
                        <span class="{{ results[col.field] }} active"></span>
                      </div>
                    </div>

                    <!--[popover]="popTemplateTranslation" popoverTitle="{{'app.ipim-mytextedit.trafficlight.popover.title' | translate}}"
                        placement="top" container="body" triggers="mouseenter:mouseleave"-->

                    <div *ngSwitchCase="'channels'">
                      <div
                        *ngFor="let channel of results[col.field]"
                        class="nm-inline-images"
                      >
                        <ng-template #popTemplateTranslation>
                          <div class="translation-status-list">
                            <div
                              *ngFor="let marketplace of channel.marketplaces"
                              class="translation-status"
                            >
                              <div>Name: {{ marketplace.name }}</div>
                              <div>Identifer: {{ marketplace.identifier }}</div>
                              <div>Sprache: {{ marketplace.language }}</div>
                            </div>
                          </div>
                        </ng-template>
                        <div
                          [popover]="popTemplateTranslation"
                          popoverTitle="{{ 'table.head.channels' | translate }}"
                          placement="right"
                          container="body"
                          triggers="mouseenter:mouseleave"
                        >
                          <!-- TODO fix array channel.marketplaces[0] -->
                          <a
                            (click)="
                              showDetails([
                                this.dataType.substring(
                                  0,
                                  this.dataType.length - 1
                                ),
                                results.identifier,
                                channel.marketplaces[0].identifier
                              ])
                            "
                          >
                            <nm-image
                              [container]="channel.image"
                              asset="image"
                              size="preview"
                              width="auto"
                              height="auto"
                              max-width="58px"
                              max-height="58px"
                            ></nm-image>
                          </a>
                        </div>
                      </div>
                    </div>

                    <div *ngSwitchCase="'created'">
                      {{ results[col.field] | date: "medium" }}
                    </div>

                    <div *ngSwitchCase="'articleNo'">
                      <a
                        (click)="showDetails(['articles', results.identifier])"
                      >
                        <nm-ellipsis
                          [content]="results.identifier"
                        ></nm-ellipsis>
                      </a>
                    </div>

                    <div *ngSwitchCase="'variants'">
                      <div *ngFor="let variant of results.variants">
                        <a
                          (click)="
                            showDetails([
                              'articles',
                              results.identifier,
                              variant.sku
                            ])
                          "
                        >
                          {{ variant.identifier }}
                        </a>
                      </div>
                    </div>

                    <div *ngSwitchCase="'customer'">
                      <div>{{ results[col.field] | customerDetails }}</div>
                    </div>

                    <div *ngSwitchCase="'marektplace'">
                      <div>{{ results[col.field].name }}</div>
                    </div>

                    <div *ngSwitchCase="'interactions'">
                      <nm-interactions
                        [param]="results"
                        [selectors]="selectors()"
                      ></nm-interactions>
                    </div>

                    <div *ngSwitchCase="'type'">
                      <div
                        *ngIf="
                          dataType == 'content-assets' ||
                          dataType == 'content-relations'
                        "
                      >
                        <mat-form-field class="editable-field">
                          <mat-select
                            [value]="results[col.field]"
                            name="editable-type"
                            [(ngModel)]="results[col.field]"
                            (selectionChange)="
                              dropdownValueChanged(results, rowIndex)
                            "
                          >
                            <mat-option
                              *ngFor="let data of dropdownsData[col.field]"
                              [value]="data.id"
                            >
                              {{ data.description }}
                            </mat-option>
                          </mat-select>
                        </mat-form-field>
                      </div>
                      <div
                        *ngIf="
                          dataType != 'content-assets' &&
                          dataType != 'content-relations'
                        "
                      >
                        <nm-ellipsis
                          [content]="results[col.field]"
                        ></nm-ellipsis>
                      </div>
                    </div>

                    <div *ngSwitchCase="'asset-type'">
                      <div *ngIf="dataType == 'assets'">
                        <mat-form-field class="editable-field">
                          <mat-select
                            #model="ngModel"
                            [value]="results[col.field]"
                            name="editable-type"
                            [(ngModel)]="results[col.field]"
                            (selectionChange)="
                              dropdownValueChanged(results, rowIndex)
                            "
                          >
                            <mat-option (click)="model.reset()"></mat-option>
                            <mat-option
                              *ngFor="let data of dropdownsData[col.field]"
                              [value]="data.id"
                            >
                              {{ data.description }}
                            </mat-option>
                          </mat-select>
                        </mat-form-field>
                      </div>
                      <div *ngIf="dataType != 'assets'">
                        <nm-ellipsis
                          [content]="results[col.field]"
                        ></nm-ellipsis>
                      </div>
                    </div>

                    <div *ngSwitchCase="'rel-type'">
                      <div *ngIf="dataType == 'content'">
                        <mat-form-field class="editable-field">
                          <mat-select
                            #model="ngModel"
                            [value]="results[col.field]"
                            name="editable-type"
                            [(ngModel)]="results[col.field]"
                            (selectionChange)="
                              dropdownValueChanged(results, rowIndex)
                            "
                          >
                            <mat-option (click)="model.reset()"></mat-option>
                            <mat-option
                              *ngFor="let data of dropdownsData[col.field]"
                              [value]="data.id"
                            >
                              {{ data.description }}
                            </mat-option>
                          </mat-select>
                        </mat-form-field>
                      </div>
                      <div *ngIf="dataType != 'content'">
                        <nm-ellipsis
                          [content]="results[col.field]"
                        ></nm-ellipsis>
                      </div>
                    </div>

                    <div *ngSwitchCase="'direction'">
                      <div
                        *ngIf="
                          dataType == 'content-relations' ||
                          dataType == 'content'
                        "
                      >
                        <mat-form-field class="editable-field">
                          <mat-select
                            #model="ngModel"
                            [value]="results[col.field]"
                            name="editable-type"
                            [(ngModel)]="results[col.field]"
                            (selectionChange)="
                              dropdownValueChanged(results, rowIndex)
                            "
                          >
                            <mat-option (click)="model.reset()"></mat-option>
                            <mat-option
                              *ngFor="let data of dropdownsData[col.field]"
                              [value]="data.id"
                            >
                              {{ data.description }}
                            </mat-option>
                          </mat-select>
                        </mat-form-field>
                      </div>
                    </div>

                    <div *ngSwitchDefault class="nm-break">
                      <div
                        *ngIf="col.field != 'order' && col.field != 'sequence'"
                      >
                        <nm-ellipsis
                          [content]="results[col.field]"
                        ></nm-ellipsis>
                      </div>

                      <div
                        *ngIf="col.field == 'order' || col.field == 'sequence'"
                      >
                        <mat-form-field class="editable-field">
                          <input
                            (input)="onChangeNumberField(results, rowIndex)"
                            matInput
                            type="number"
                            min="0"
                            maxlength="10"
                            oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);"
                            [(ngModel)]="results[col.field]"
                            [readonly]="false"
                          />
                        </mat-form-field>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </ng-container>
          </ng-template>
        </p-column>
        <footer>
          <div class="ui-helper-clearfix" style="width: 100%"></div>
        </footer>
      </p-dataTable>

      <div class="viewmodeList" *ngIf="isViewmodeList">
        <p-dataGrid
          [value]="results | async"
          (onLazyLoad)="loadData($event)"
          [paginator]="false"
          [rows]="limit"
          [lazy]="true"
          [totalRecords]="total | async"
          class="wrap"
          emptyMessage=""
          #dg
        >
          <p-header>
            <div *ngFor="let col of cols | async" class="nm-sort-header">
              <span
                class="ui-sortable-column-icon fa fa-fw fa-sort"
                (click)="onSortingChanged($event, col)"
                *ngIf="col.sortable"
                [ngClass]="{
                  'fa-sort-desc': getSortOrder(col) == -1,
                  'fa-sort-asc': getSortOrder(col) == 1
                }"
              ></span>
              <mat-form-field *ngIf="col.filter">
                <input
                  matInput
                  placeholder="{{ col.header | translate }}"
                  [value]="
                    lastPrimeNGEvent?.filters[col.field]
                      ? lastPrimeNGEvent?.filters[col.field]?.value
                      : ''
                  "
                  type="text"
                  class="ui-column-filter"
                  (input)="onFilterKeyup($event.target.value, col.field)"
                />
              </mat-form-field>
            </div>
          </p-header>
          <ng-template let-entry pTemplate="item">
            <p-panel
              class="nm-gridlist-box"
              [style.width]="boxWidth"
              [style.padding-bottom]="boxHeight"
            >
              <div class="nm-gridlist-boxInner">
                <div class="nm-gridlist-actionBox">
                  <nm-action-icon
                    *ngIf="entry._actions"
                    [action]="entry._actions['add-to-cart']"
                    [name]="'add-to-cart'"
                  >
                  </nm-action-icon>
                </div>
                <nm-image
                  [container]="entry"
                  asset="main-asset"
                  size="preview"
                  width="auto"
                  height="auto"
                  alt="{{ entry.identifier }}"
                ></nm-image>
                <div
                  class="nm-gridlist-titleBox"
                  (click)="
                    showDetails([
                      this.dataType.substring(0, this.dataType.length - 1),
                      entry.identifier
                    ])
                  "
                >
                  <span> {{ entry.identifier }}</span>
                  <div>{{ entry.description }}</div>
                </div>
              </div>
            </p-panel>
          </ng-template>
        </p-dataGrid>
      </div>
    </div>
  </div>
</nm-widgetframe>
<!-- TODO: Make it more generic -->
<button
  mat-mini-fab
  color="primary"
  mat-elevation-z0
  *ngFor="let act of multiselectaction | async | iterable"
  [nm-action]="act.value"
  [action-name]="act.key"
  [action-payload]="multiselectpayload | async"
  matTooltip="{{ 'infotext.addselectiontocart' | translate }}"
  class="mat-icon-button mat-elevation-z0 nm-button__addSelction"
  [class.nm-fadein]="isMultiselectActionNeeded"
>
  <div
    class="material-icons nm-svg-icon"
    [ngStyle]="{ fill: 'rgb(255,153,0)' }"
  >
    <mat-icon>add_shopping_cart</mat-icon>
  </div>
</button>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""